Changeset 501


Ignore:
Timestamp:
Nov 7, 2010, 11:24:13 PM (14 years ago)
Author:
frichard
Message:

-BAOControl : petite interface permettant de contrôler les antennes via le pilote indi_BAO
-Le pilote indi_BAO utilise désormais libindi v 0.7

Location:
BAORadio
Files:
10 added
21 edited

Legend:

Unmodified
Added
Removed
  • BAORadio/libindi/libindi/BAOTest/simple_server_main.cpp

    r490 r501  
    1010    {
    1111      // Create the socket
    12       ServerSocket server ( 8000 );
     12      ServerSocket server ( 7624 );
    1313
    1414      while ( true )
  • BAORadio/libindi/libindi/CMakeLists.txt

    r490 r501  
    11cmake_minimum_required(VERSION 2.4.7)
    22
     3 if(COMMAND cmake_policy)
     4      cmake_policy(SET CMP0003 NEW)
     5    endif(COMMAND cmake_policy)
     6
     7
    38
    49##################  INDI version  ################################
    5 set(INDI_VERSION "0.6")
    610set(INDI_SOVERSION "0")
    7 
    811set(CMAKE_INDI_VERSION_MAJOR 0)
    9 set(CMAKE_INDI_VERSION_MINOR 6)
    10 set(CMAKE_INDI_VERSION_RELEASE 1)
     12set(CMAKE_INDI_VERSION_MINOR 7)
     13set(CMAKE_INDI_VERSION_RELEASE 0)
    1114set(CMAKE_INDI_VERSION_STRING "${CMAKE_INDI_VERSION_MAJOR}.${CMAKE_INDI_VERSION_MINOR}.${CMAKE_INDI_VERSION_RELEASE}")
    1215
     
    5154macro_log_feature(FLI_FOUND "libfli" "Finger Lakes Instrument Library" "http://indi.sourceforge.net/" FALSE "1.71" "Provides INDI with support for controlling FLI CCDS & Filter Wheels.")
    5255
    53 
    5456macro_optional_find_package(Nova)
    5557macro_bool_to_01(NOVA_FOUND HAVE_NOVA_H)
     
    5961check_include_files(termios.h TERMIOS_FOUND)
    6062macro_bool_to_01(TERMIOS_FOUND HAVE_TERMIOS_H)
    61 
    62 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h )
    6363
    6464include_directories( ${CMAKE_CURRENT_BINARY_DIR})
     
    9595
    9696set (indimain_SRCS
     97        ${CMAKE_SOURCE_DIR}/indidriver.c
    9798        ${CMAKE_SOURCE_DIR}/indidrivermain.c
    9899        ${CMAKE_SOURCE_DIR}/eventloop.c
    99100    )
    100101
     102set (indibase_SRCS
     103        ${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.cpp
     104        ${CMAKE_SOURCE_DIR}/libs/indibase/baseclient.cpp
     105    )
     106
     107set (indidefaultdevice_SRCS
     108        ${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.cpp
     109        ${CMAKE_SOURCE_DIR}/libs/indibase/defaultdriver.cpp
     110    )
     111
     112
    101113######################################
    102114########### INDI SERVER ##############
     
    115127install(TARGETS indiserver RUNTIME DESTINATION bin )
    116128
    117 ######################################
    118 ######## INDI Static Library #########
    119 ######################################
    120 add_library(indidriver STATIC ${indimain_SRCS})
    121 install(TARGETS indidriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
    122129
    123130######################################
     
    138145
    139146install(TARGETS indi LIBRARY DESTINATION lib${LIB_POSTFIX})
    140 set_target_properties(indi PROPERTIES VERSION ${INDI_VERSION} SOVERSION ${INDI_SOVERSION})
     147set_target_properties(indi PROPERTIES VERSION ${CMAKE_INDI_VERSION_STRING} SOVERSION ${INDI_SOVERSION})
     148
     149
     150######################################
     151######## INDI Static Library #########
     152######################################
     153add_library(indidriver STATIC ${indimain_SRCS})
     154install(TARGETS indidriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
     155
     156##############################################
     157######## INDI Default Driver Library #########
     158##############################################
     159add_library(indidefaultdriver STATIC ${indimain_SRCS} ${indidefaultdevice_SRCS})
     160install(TARGETS indidefaultdriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
     161
     162##############################################
     163######## INDI Client Library #########
     164##############################################
     165add_library(indiclient STATIC ${indibase_SRCS})
     166target_link_libraries(indiclient indi)
     167install(TARGETS indiclient ARCHIVE DESTINATION lib${LIB_POSTFIX})
    141168
    142169#####################################
     
    202229target_link_libraries(indi_celestron_gps m )
    203230
     231
    204232if (NOVA_FOUND)
    205233  target_link_libraries(indi_celestron_gps ${NOVA_LIBRARIES})
     
    601629endif (NOVA_FOUND)
    602630
     631########### Tutorial four ##############
     632set(tutorialfour_SRCS
     633        ${indimain_SRCS}
     634        ${CMAKE_SOURCE_DIR}/examples/tutorial_four.cpp
     635   )
     636
     637add_executable(tutorial_four ${tutorialfour_SRCS} ${liblilxml_SRCS} ${libindicom_SRCS})
     638
     639target_link_libraries(tutorial_four indidefaultdriver indiclient m z pthread)
     640
     641if (NOVA_FOUND)
     642  target_link_libraries(tutorial_four ${NOVA_LIBRARIES})
     643endif (NOVA_FOUND)
     644
     645
    603646########### Tutorial dome ##############
    604647set(tutorialdome_SRCS
     
    633676install( FILES drivers.xml DESTINATION ${DATA_INSTALL_DIR})
    634677
    635 install( FILES indiapi.h indidevapi.h base64.h eventloop.h ${CMAKE_SOURCE_DIR}/libs/lilxml.h
    636  ${CMAKE_SOURCE_DIR}/libs/indicom.h DESTINATION ${INCLUDE_INSTALL_DIR}/libindi COMPONENT Devel)
     678install( FILES indiapi.h indidevapi.h base64.h eventloop.h indidriver.h ${CMAKE_SOURCE_DIR}/libs/lilxml.h ${CMAKE_SOURCE_DIR}/libs/indibase/indibase.h
     679${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.h  ${CMAKE_SOURCE_DIR}/libs/indibase/defaultdriver.h
     680${CMAKE_SOURCE_DIR}/libs/indibase/baseclient.h ${CMAKE_SOURCE_DIR}/libs/indicom.h
     681 DESTINATION ${INCLUDE_INSTALL_DIR}/libindi COMPONENT Devel)
    637682
    638683configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libindi.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libindi.pc @ONLY)
  • BAORadio/libindi/libindi/ChangeLog

    r490 r501  
     1From 0.6.2 to 0.7.0
     2
     3      # Dynamic renaming of drivers upon run time.
     4      # Standard helper API to create and utilize INDI clients.
     5      # Ability to load driver properties from an external XML file.
     6      # Ability to write/read XML configuration files for driver values to be loaded at run time.
     7      # Facilitating debugging and simulation of drivers.
     8      # New C++ framework to facilitate the development of new INDI drivers.
     9      # Several bug fixes for current drivers and framework.
     10
     11From 0.6.1 to 0.6.2
     12
     13        # Build related updates.
     14
     15From 0.6 to 0.6.1
     16
     17        # Updating drivers.xml to comply to new XML structure for group and devices metadata descriptions.
     18
    119From 0.5 to 0.6
    220
  • BAORadio/libindi/libindi/Doxyfile

    r490 r501  
    1 # Doxyfile 1.4.1-KDevelop
     1# Doxyfile 1.7.1
    22
    33#---------------------------------------------------------------------------
    44# Project related configuration options
    55#---------------------------------------------------------------------------
     6DOXYFILE_ENCODING      = UTF-8
    67PROJECT_NAME           = "Instrument Neutral Distributed Interface INDI"
    78PROJECT_NUMBER         = 0.7
     
    910CREATE_SUBDIRS         = NO
    1011OUTPUT_LANGUAGE        = English
    11 USE_WINDOWS_ENCODING   = NO
    1212BRIEF_MEMBER_DESC      = YES
    1313REPEAT_BRIEF           = YES
    14 ABBREVIATE_BRIEF       = 
     14ABBREVIATE_BRIEF       =
    1515ALWAYS_DETAILED_SEC    = NO
    1616INLINE_INHERITED_MEMB  = NO
    1717FULL_PATH_NAMES        = NO
    18 STRIP_FROM_PATH        = 
    19 STRIP_FROM_INC_PATH    = 
     18STRIP_FROM_PATH        =
     19STRIP_FROM_INC_PATH    =
    2020SHORT_NAMES            = NO
    2121JAVADOC_AUTOBRIEF      = NO
     22QT_AUTOBRIEF           = NO
    2223MULTILINE_CPP_IS_BRIEF = NO
    23 DETAILS_AT_TOP         = NO
    2424INHERIT_DOCS           = YES
    25 DISTRIBUTE_GROUP_DOC   = NO
     25SEPARATE_MEMBER_PAGES  = NO
    2626TAB_SIZE               = 8
    27 ALIASES                = 
     27ALIASES                =
    2828OPTIMIZE_OUTPUT_FOR_C  = NO
    2929OPTIMIZE_OUTPUT_JAVA   = NO
     30OPTIMIZE_FOR_FORTRAN   = NO
     31OPTIMIZE_OUTPUT_VHDL   = NO
     32EXTENSION_MAPPING      =
     33BUILTIN_STL_SUPPORT    = NO
     34CPP_CLI_SUPPORT        = NO
     35SIP_SUPPORT            = NO
     36IDL_PROPERTY_SUPPORT   = YES
     37DISTRIBUTE_GROUP_DOC   = NO
    3038SUBGROUPING            = YES
     39TYPEDEF_HIDES_STRUCT   = NO
     40SYMBOL_CACHE_SIZE      = 0
    3141#---------------------------------------------------------------------------
    3242# Build related configuration options
     
    3747EXTRACT_LOCAL_CLASSES  = YES
    3848EXTRACT_LOCAL_METHODS  = NO
     49EXTRACT_ANON_NSPACES   = NO
    3950HIDE_UNDOC_MEMBERS     = YES
    4051HIDE_UNDOC_CLASSES     = YES
     
    4556HIDE_SCOPE_NAMES       = NO
    4657SHOW_INCLUDE_FILES     = YES
     58FORCE_LOCAL_INCLUDES   = NO
    4759INLINE_INFO            = YES
    4860SORT_MEMBER_DOCS       = YES
    4961SORT_BRIEF_DOCS        = NO
     62SORT_MEMBERS_CTORS_1ST = NO
     63SORT_GROUP_NAMES       = NO
    5064SORT_BY_SCOPE_NAME     = NO
    5165GENERATE_TODOLIST      = YES
     
    5367GENERATE_BUGLIST       = YES
    5468GENERATE_DEPRECATEDLIST= YES
    55 ENABLED_SECTIONS       = 
     69ENABLED_SECTIONS       =
    5670MAX_INITIALIZER_LINES  = 30
    5771SHOW_USED_FILES        = YES
    5872SHOW_DIRECTORIES       = YES
    59 FILE_VERSION_FILTER    =
     73SHOW_FILES             = YES
     74SHOW_NAMESPACES        = YES
     75FILE_VERSION_FILTER    =
     76LAYOUT_FILE            =
    6077#---------------------------------------------------------------------------
    6178# configuration options related to warning and progress messages
     
    6784WARN_NO_PARAMDOC       = NO
    6885WARN_FORMAT            = "$file:$line: $text"
    69 WARN_LOGFILE           = 
     86WARN_LOGFILE           =
    7087#---------------------------------------------------------------------------
    7188# configuration options related to the input files
    7289#---------------------------------------------------------------------------
    73 INPUT                  = /home/jasem/Projects/trunk/libindi
     90INPUT                  = /home/jasem/Projects/indi/trunk/libindi
     91INPUT_ENCODING         = UTF-8
    7492FILE_PATTERNS          = *.c \
    7593                         *.cc \
     
    103121                         *.dox
    104122RECURSIVE              = YES
    105 EXCLUDE                = /home/jasem/Projects/trunk/libindi/drivers \
    106                          /home/jasem/Projects/trunk/libindi/tools \
    107                          /home/jasem/Projects/trunk/libindi/libs/webcam \
    108                          /home/jasem/Projects/trunk/libindi/libs/base64.c \
    109                          /home/jasem/Projects/trunk/libindi/libs/fq.c \
    110                          /home/jasem/Projects/trunk/libindi/indidrivermain.c \
    111                          /home/jasem/Projects/trunk/libindi/indiserver.c
     123EXCLUDE                = /home/jasem/Projects/indi/trunk/libindi/drivers \
     124                         /home/jasem/Projects/indi/trunk/libindi/tools \
     125                         /home/jasem/Projects/indi/trunk/libindi/libs/webcam \
     126                         /home/jasem/Projects/indi/trunk/libindi/libs/base64.c \
     127                         /home/jasem/Projects/indi/trunk/libindi/libs/fq.c \
     128                         /home/jasem/Projects/indi/trunk/libindi/indidrivermain.c \
     129                         /home/jasem/Projects/indi/trunk/libindi/indiserver.c
    112130EXCLUDE_SYMLINKS       = NO
    113 EXCLUDE_PATTERNS       =
    114 EXAMPLE_PATH           =
     131EXCLUDE_PATTERNS       =
     132EXCLUDE_SYMBOLS        =
     133EXAMPLE_PATH           =
    115134EXAMPLE_PATTERNS       = *
    116135EXAMPLE_RECURSIVE      = NO
    117 IMAGE_PATH             = 
    118 INPUT_FILTER           = 
    119 FILTER_PATTERNS        = 
     136IMAGE_PATH             =
     137INPUT_FILTER           =
     138FILTER_PATTERNS        =
    120139FILTER_SOURCE_FILES    = NO
    121140#---------------------------------------------------------------------------
     
    127146REFERENCED_BY_RELATION = NO
    128147REFERENCES_RELATION    = NO
     148REFERENCES_LINK_SOURCE = YES
     149USE_HTAGS              = NO
    129150VERBATIM_HEADERS       = NO
    130151#---------------------------------------------------------------------------
     
    133154ALPHABETICAL_INDEX     = YES
    134155COLS_IN_ALPHA_INDEX    = 5
    135 IGNORE_PREFIX          = 
     156IGNORE_PREFIX          =
    136157#---------------------------------------------------------------------------
    137158# configuration options related to the HTML output
     
    140161HTML_OUTPUT            = doc
    141162HTML_FILE_EXTENSION    = .html
    142 HTML_HEADER            =
    143 HTML_FOOTER            =
    144 HTML_STYLESHEET        =
     163HTML_HEADER            =
     164HTML_FOOTER            =
     165HTML_STYLESHEET        =
     166HTML_COLORSTYLE_HUE    = 220
     167HTML_COLORSTYLE_SAT    = 100
     168HTML_COLORSTYLE_GAMMA  = 80
     169HTML_TIMESTAMP         = YES
    145170HTML_ALIGN_MEMBERS     = YES
     171HTML_DYNAMIC_SECTIONS  = NO
     172GENERATE_DOCSET        = NO
     173DOCSET_FEEDNAME        = "Doxygen generated docs"
     174DOCSET_BUNDLE_ID       = org.doxygen.Project
     175DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
     176DOCSET_PUBLISHER_NAME  = Publisher
    146177GENERATE_HTMLHELP      = NO
    147 CHM_FILE               = 
    148 HHC_LOCATION           = 
     178CHM_FILE               =
     179HHC_LOCATION           =
    149180GENERATE_CHI           = NO
     181CHM_INDEX_ENCODING     =
    150182BINARY_TOC             = NO
    151183TOC_EXPAND             = NO
     184GENERATE_QHP           = NO
     185QCH_FILE               =
     186QHP_NAMESPACE          = org.doxygen.Project
     187QHP_VIRTUAL_FOLDER     = doc
     188QHP_CUST_FILTER_NAME   =
     189QHP_CUST_FILTER_ATTRS  =
     190QHP_SECT_FILTER_ATTRS  =
     191QHG_LOCATION           =
     192GENERATE_ECLIPSEHELP   = NO
     193ECLIPSE_DOC_ID         = org.doxygen.Project
    152194DISABLE_INDEX          = NO
    153195ENUM_VALUES_PER_LINE   = 4
    154196GENERATE_TREEVIEW      = NO
     197USE_INLINE_TREES       = NO
    155198TREEVIEW_WIDTH         = 250
     199EXT_LINKS_IN_WINDOW    = NO
     200FORMULA_FONTSIZE       = 10
     201FORMULA_TRANSPARENT    = YES
     202SEARCHENGINE           = NO
     203SERVER_BASED_SEARCH    = NO
    156204#---------------------------------------------------------------------------
    157205# configuration options related to the LaTeX output
     
    163211COMPACT_LATEX          = NO
    164212PAPER_TYPE             = a4wide
    165 EXTRA_PACKAGES         = 
    166 LATEX_HEADER           = 
     213EXTRA_PACKAGES         =
     214LATEX_HEADER           =
    167215PDF_HYPERLINKS         = NO
    168216USE_PDFLATEX           = NO
    169217LATEX_BATCHMODE        = NO
    170218LATEX_HIDE_INDICES     = NO
     219LATEX_SOURCE_CODE      = NO
    171220#---------------------------------------------------------------------------
    172221# configuration options related to the RTF output
     
    176225COMPACT_RTF            = NO
    177226RTF_HYPERLINKS         = NO
    178 RTF_STYLESHEET_FILE    = 
    179 RTF_EXTENSIONS_FILE    = 
     227RTF_STYLESHEET_FILE    =
     228RTF_EXTENSIONS_FILE    =
    180229#---------------------------------------------------------------------------
    181230# configuration options related to the man page output
     
    190239GENERATE_XML           = NO
    191240XML_OUTPUT             = xml
    192 XML_SCHEMA             = 
    193 XML_DTD                = 
     241XML_SCHEMA             =
     242XML_DTD                =
    194243XML_PROGRAMLISTING     = YES
    195244#---------------------------------------------------------------------------
     
    203252PERLMOD_LATEX          = NO
    204253PERLMOD_PRETTY         = YES
    205 PERLMOD_MAKEVAR_PREFIX = 
    206 #---------------------------------------------------------------------------
    207 # Configuration options related to the preprocessor   
     254PERLMOD_MAKEVAR_PREFIX =
     255#---------------------------------------------------------------------------
     256# Configuration options related to the preprocessor
    208257#---------------------------------------------------------------------------
    209258ENABLE_PREPROCESSING   = YES
     
    211260EXPAND_ONLY_PREDEF     = NO
    212261SEARCH_INCLUDES        = YES
    213 INCLUDE_PATH           = 
    214 INCLUDE_FILE_PATTERNS  = 
    215 PREDEFINED             = 
    216 EXPAND_AS_DEFINED      = 
     262INCLUDE_PATH           =
     263INCLUDE_FILE_PATTERNS  =
     264PREDEFINED             =
     265EXPAND_AS_DEFINED      =
    217266SKIP_FUNCTION_MACROS   = YES
    218267#---------------------------------------------------------------------------
    219 # Configuration::additions related to external references   
    220 #---------------------------------------------------------------------------
    221 TAGFILES               = 
    222 GENERATE_TAGFILE       = 
     268# Configuration::additions related to external references
     269#---------------------------------------------------------------------------
     270TAGFILES               =
     271GENERATE_TAGFILE       =
    223272ALLEXTERNALS           = NO
    224273EXTERNAL_GROUPS        = YES
    225274PERL_PATH              = /usr/bin/perl
    226275#---------------------------------------------------------------------------
    227 # Configuration options related to the dot tool   
     276# Configuration options related to the dot tool
    228277#---------------------------------------------------------------------------
    229278CLASS_DIAGRAMS         = YES
     279MSCGEN_PATH            =
    230280HIDE_UNDOC_RELATIONS   = YES
    231281HAVE_DOT               = NO
     282DOT_NUM_THREADS        = 0
     283DOT_FONTNAME           = FreeSans.ttf
     284DOT_FONTSIZE           = 10
     285DOT_FONTPATH           =
    232286CLASS_GRAPH            = YES
    233287COLLABORATION_GRAPH    = YES
     
    238292INCLUDED_BY_GRAPH      = YES
    239293CALL_GRAPH             = NO
     294CALLER_GRAPH           = NO
    240295GRAPHICAL_HIERARCHY    = YES
    241296DIRECTORY_GRAPH        = YES
    242297DOT_IMAGE_FORMAT       = png
    243 DOT_PATH               =
    244 DOTFILE_DIRS           =
    245 MAX_DOT_GRAPH_WIDTH    = 1024
    246 MAX_DOT_GRAPH_HEIGHT   = 1024
     298DOT_PATH               =
     299DOTFILE_DIRS           =
     300DOT_GRAPH_MAX_NODES    = 50
    247301MAX_DOT_GRAPH_DEPTH    = 1000
    248302DOT_TRANSPARENT        = NO
     
    250304GENERATE_LEGEND        = YES
    251305DOT_CLEANUP            = YES
    252 #---------------------------------------------------------------------------
    253 # Configuration::additions related to the search engine   
    254 #---------------------------------------------------------------------------
    255 SEARCHENGINE           = NO
  • BAORadio/libindi/libindi/INSTALL

    r490 r501  
    1 INDI Library Setup 0.6.1
     1INDI Library Setup 0.7.0
    22========================
    33
  • BAORadio/libindi/libindi/NEWS

    r490 r501  
    33-------------------------------------------------------------------------
    44
    5 For the latest news on INDI, refer to INDI's website @ http://indi.sf.net
     5For the latest news on INDI, refer to INDI's website @ http://www.indilib.org
    66
  • BAORadio/libindi/libindi/README

    r490 r501  
     1libindi v0.6.2
     2==============
     3
    14The code here demonstrates the use of INDI, an Instrument-Neutral Device
    25Interface protocol. See http://www.clearskyinstitute.com/INDI/INDI.pdf.
  • BAORadio/libindi/libindi/cmake_modules/FindINDI.cmake

    r490 r501  
    55#  INDI_INCLUDE_DIR - the INDI include directory
    66#  INDI_LIBRARIES - Link these to use INDI
     7#  INDI_DEVICE_LIBRARY - The indi default device library
     8#  INDI_DATA_DIR - INDI shared data dir.
    79
    8 # Copyright (c) 2006, Jasem Mutlaq <mutlaqja@ikarustech.com>
     10# Copyright (c) 2010, Jasem Mutlaq <mutlaqja@ikarustech.com>
    911# Based on FindLibfacile by Carsten Niehaus, <cniehaus@gmx.de>
    1012#
     
    2729  )
    2830
     31 find_path(INDI_DATA_DIR drivers.xml
     32    PATH_SUFFIXES indi
     33    /usr
     34    /usr/local
     35    /opt
     36    ${GNUWIN32_DIR}/share
     37  )
     38
    2939  find_library(INDI_DRIVER_LIBRARIES NAMES indidriver
    3040    PATHS
     
    3242    ${GNUWIN32_DIR}/lib
    3343  )
     44
     45  find_library(INDI_DEVICE_LIBRARIES NAMES indidefaultdevice
     46    PATHS
     47    ${_obLinkDir}
     48    ${GNUWIN32_DIR}/lib
     49  )
     50
    3451
    3552  find_library(INDI_LIBRARIES NAMES indi
     
    5269  else (INDI_FOUND)
    5370    if (INDI_FIND_REQUIRED)
    54       message(FATAL_ERROR "indi-devel not found. Cannot compile INDI drivers. Please install indi-devel and try again. http://indi.sf.net")
     71      message(FATAL_ERROR "indi-devel not found. Cannot compile INDI drivers. Please install indi-devel and try again. http://www.indilib.org")
    5572    endif (INDI_FIND_REQUIRED)
    5673  endif (INDI_FOUND)
    5774
    58   mark_as_advanced(INDI_INCLUDE_DIR INDI_LIBRARIES INDI_DRIVER_LIBRARIES)
     75  mark_as_advanced(INDI_INCLUDE_DIR INDI_LIBRARIES INDI_DRIVER_LIBRARIES INDI_DEVICE_LIBRARIES INDI_DATA_DIR)
    5976
    6077endif (INDI_INCLUDE_DIR AND INDI_LIBRARIES AND INDI_DRIVER_LIBRARIES)
  • BAORadio/libindi/libindi/drivers/filter_wheel/trutech_wheel.c

    r490 r501  
    7070#define FIRST_FILTER                    1
    7171
     72#define DEBUG_ON                        0
     73#define SIMULATION_ON                   0
     74
    7275
    7376/*INDI controls */
     
    166169                unsigned char chksum = COMM_INIT + type + COMM_FILL;
    167170                /*char filter_command[5] = { COMM_PRE, COMM_INIT, type, COMM_FILL, chksum };*/
    168                 char filter_command[CMD_SIZE];
     171                unsigned char filter_command[CMD_SIZE];
    169172                snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
    170173
     
    172175                        return;
    173176
    174                 err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
    175                
     177                if (!SIMULATION_ON)
     178                    err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
     179
     180
     181                if (DEBUG_ON)
     182                {
     183                    IDLog("Home Search Command (int): #%d#%d#%d#%d#%d#\n",COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
     184                    IDLog("Home Search Command (char): #%c#%c#%c#%c#%c#\n",COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
     185                }
     186
    176187                /* Send Home Command */
    177188                if (err != TTY_OK)
     
    247258                        targetFilter = values[0];
    248259                        int nbytes=0;
    249                         char type = 0x01;
    250                         char chksum = COMM_INIT + type + (char) targetFilter;
     260                        unsigned char type = 0x01;
     261                        unsigned char chksum = COMM_INIT + type + (unsigned char) targetFilter;
    251262                        /*char filter_command[5] = { COMM_PRE, COMM_INIT, type, targetFilter, chksum };*/
    252                         char filter_command[CMD_SIZE];
    253 
    254                         snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
     263                        unsigned char filter_command[CMD_SIZE];
     264
    255265
    256266                        if (targetFilter < FilterPositionN[0].min || targetFilter > FilterPositionN[0].max)
     
    262272
    263273                        IUUpdateNumber(&FilterPositionNP, values, names, n);
    264                         err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
     274
     275                        snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, targetFilter, chksum);
     276
     277                        if (DEBUG_ON)
     278                        {
     279                            IDLog("Filter Position Command (int): #%d#%d#%d#%d#%d#\n",COMM_PRE, COMM_INIT, type, targetFilter, chksum);
     280                            IDLog("Filter Position Command (char): #%c#%c#%c#%c#%c#\n",COMM_PRE, COMM_INIT, type, targetFilter, chksum);
     281                        }
     282
     283                        if (!SIMULATION_ON)
     284                            err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
     285
    265286
    266287                        FilterPositionNP.s = IPS_OK;
     
    385406        {
    386407                case ISS_ON:
     408                        if (SIMULATION_ON)
     409                        {
     410                            PowerSP.s = IPS_OK;
     411                            IDSetSwitch(&PowerSP, "Simulated Filter Wheel is online.");
     412                            return;
     413                        }
     414
    387415                        if ( (err = tty_connect(PortT[0].text, 9600, 8, 0, 1, &fd)) != TTY_OK)
    388416                        {
     
    394422                        }
    395423
     424
    396425                        PowerSP.s = IPS_OK;
    397426                        IDSetSwitch(&PowerSP, "Filter Wheel is online. True Technology filter wheel suffers from several bugs. Please refer to http://indi.sf.net/profiles/trutech.html for more details.");
     
    399428               
    400429                case ISS_OFF:
     430                        if (SIMULATION_ON)
     431                        {
     432                          PowerSP.s = IPS_OK;
     433                          IDSetSwitch(&PowerSP, "Simulated Filter Wheel is offline.");
     434                          return;
     435                        }
     436
    401437                        if ( (err = tty_disconnect(fd)) != TTY_OK)
    402438                        {
  • BAORadio/libindi/libindi/drivers/telescope/BAO.cpp

    r499 r501  
    1   #if 0
    2  
    3   #############################
    4   ##
    5   ## BAORadio Indi driver
    6   ## Franck RICHARD
    7   ## Mai 2010
    8   ##
    9   #############################
    10   #endif
    11  
    12   #include <stdio.h>
    13   #include <stdlib.h>
    14   #include <string.h>
    15   #include <stdarg.h>
    16   #include <math.h>
    17   #include <unistd.h>
    18   #include <time.h>
    19   #include <memory>
    20   #include <pthread.h>
    21   #include <iostream>
    22   #include <time.h>
    23   #include <unistd.h>
    24   #include <sys/time.h>
    25  
    26   #include <config.h>
    27  
    28   #include "indicom.h"
    29  
    30   #include "Socket.h"
    31  
    32   #include "BAO.h"
    33  
    34   using namespace std;
    35  
    36   auto_ptr<BAO> telescope(0);
    37  
    38   const int POLLMS = 1;                         // Period of update, 1 ms.
    39  
    40   const char *mydev = "BAO";                    // Name of our device.
    41  
    42   const char *BASIC_GROUP    = "Main Control";          // Main Group
    43   const char *OPTIONS_GROUP  = "Options";                       // Options Group
    44  
    45   /* Handy Macros */
    46   //#define currentRA   EquatorialCoordsRN[0].value
    47   //#define currentDEC  EquatorialCoordsRN[1].value
    48   #define targetRA      EquatorialCoordsWN[0].value
    49   #define targetDEC     EquatorialCoordsWN[1].value
    50  
    51  
    52   static void ISPoll(void *);
    53  
    54   static void retry_connection(void *);
    55  
    56   /**************************************************************************************
    57   **
    58   ***************************************************************************************/
    59   void *pThreadSocket (void * arg)
    60   {
     1#if 0
     2
     3#############################
     4##
     5## BAORadio Indi driver
     6## Franck RICHARD
     7## Mai 2010
     8##
     9#############################
     10#endif
     11
     12#include <stdio.h>
     13#include <stdlib.h>
     14#include <string.h>
     15#include <stdarg.h>
     16#include <math.h>
     17#include <unistd.h>
     18#include <time.h>
     19#include <memory>
     20#include <pthread.h>
     21#include <iostream>
     22#include <time.h>
     23#include <unistd.h>
     24#include <sys/time.h>
     25
     26#include <config.h>
     27
     28#include "indicom.h"
     29
     30#include "Socket.h"
     31
     32#include "BAO.h"
     33
     34using namespace std;
     35
     36auto_ptr<BAO> telescope(0);
     37
     38const int POLLMS = 1;                           // Period of update, 1 ms.
     39
     40const char *mydev = "BAO";                      // Name of our device.
     41
     42const char *BASIC_GROUP    = "Main Control";            // Main Group
     43const char *OPTIONS_GROUP  = "Options";                 // Options Group
     44
     45/* Handy Macros */
     46//#define currentRA     EquatorialCoordsRN[0].value
     47//#define currentDEC    EquatorialCoordsRN[1].value
     48#define targetRA        EquatorialCoordsWN[0].value
     49#define targetDEC       EquatorialCoordsWN[1].value
     50
     51
     52static void ISPoll(void *);
     53
     54static void retry_connection(void *);
     55
     56/**************************************************************************************
     57**
     58***************************************************************************************/
     59void *pThreadSocket (void * arg)
     60{
    6161    try
    6262    {
    63       int pos = SocketsNumber;
    64      
    65       // Trouver éventuellement un emplacement disponible dans l'intervalle [1..SocketsNumber]
    66      
    67       /*
    68       for (int i=1; i<SocketsNumber; i++)
    69       {
    70         if (!Sockets[i].Connected)
    71         {
    72           pos = i;
    73           break;
    74     }
    75     }*/
    76      
    77       server.accept ( Sockets[pos].new_sock );
    78      
    79       Sockets[pos].IP=server.recupip(Sockets[pos].new_sock);
    80      
    81       Sockets[pos].Connected=true;
    82      
    83       if (pos == SocketsNumber ) SocketsNumber++;
    84      
    85       InitThreadOK=true;
     63        int pos = SocketsNumber;
     64
     65        // Trouver éventuellement un emplacement disponible dans l'intervalle [1..SocketsNumber]
     66
     67        /*
     68        for (int i=1; i<SocketsNumber; i++)
     69        {
     70        if (!Sockets[i].Connected)
     71        {
     72        pos = i;
     73        break;
     74        }
     75        }*/
     76
     77        server.accept ( Sockets[pos].new_sock );
     78
     79        Sockets[pos].IP=server.recupip(Sockets[pos].new_sock);
     80
     81        Sockets[pos].Connected=true;
     82
     83        if (pos == SocketsNumber ) SocketsNumber++;
     84
     85        InitThreadOK=true;
    8686    }
    8787    catch ( SocketException& e )
    8888    {
    89       //A activer pour vérif
    90      
    91       /*std::string oss;
    92       oss="pThreadSocket exception : " + e.description() + "\n";
    93       size_t size = oss.size() + 1;
    94       char* buffer = new char[size];
    95       strncpy(buffer, oss.c_str(), size);
    96      
    97       IDLog(buffer);
    98      
    99       delete [] buffer;*/
    100     }
    101    
     89        //A activer pour vérif
     90
     91        /*std::string oss;
     92        oss="pThreadSocket exception : " + e.description() + "\n";
     93        size_t size = oss.size() + 1;
     94        char* buffer = new char[size];
     95        strncpy(buffer, oss.c_str(), size);
     96
     97        IDLog(buffer);
     98
     99        delete [] buffer;*/
     100    }
     101
    102102    return NULL;
    103   }
    104  
    105  
    106   /**************************************************************************************
    107   ** Utilisation d'un thread pour éviter de bloquer l'execution du pilote
    108   ** avec la commande accept
    109   ***************************************************************************************/
    110  
    111   void BAO::InitThread()
    112   {
     103}
     104
     105
     106/**************************************************************************************
     107** Utilisation d'un thread pour éviter de bloquer l'execution du pilote
     108** avec la commande accept
     109***************************************************************************************/
     110
     111void BAO::InitThread()
     112{
    113113    if (pthread_create (&th1, NULL, pThreadSocket, NULL) < 0)
    114114    {
    115       IDLog("pthread_create error for threadSocket\n");
    116     }
    117    
     115        IDLog("pthread_create error for threadSocket\n");
     116    }
     117
    118118    pthread_join (th1, NULL);
    119   }
    120  
    121   /**************************************************************************************
    122   ** Initialisation du pilote BAO
    123   ***************************************************************************************/
    124   void ISInit()
    125   {
     119}
     120
     121/**************************************************************************************
     122** Initialisation du pilote BAO
     123***************************************************************************************/
     124void ISInit()
     125{
    126126    static int isInit=0;
    127    
     127
    128128    if (isInit) return;
    129    
     129
    130130    if (telescope.get() == 0) telescope.reset(new BAO());
    131    
     131
    132132    isInit = 1;
    133    
     133
    134134    IEAddTimer (POLLMS, ISPoll, NULL);
    135   }
    136  
    137   /**************************************************************************************
    138   **
    139   ***************************************************************************************/
    140   void ISGetProperties (const char *dev)
    141   {
     135}
     136
     137/**************************************************************************************
     138**
     139***************************************************************************************/
     140void ISGetProperties (const char *dev)
     141{
    142142    ISInit();
    143143    telescope->ISGetProperties(dev);
    144   }
    145  
    146   /**************************************************************************************
    147   **
    148   ***************************************************************************************/
    149   void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
    150   {
     144}
     145
     146/**************************************************************************************
     147**
     148***************************************************************************************/
     149void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
     150{
    151151    ISInit();
    152152    telescope->ISNewSwitch(dev, name, states, names, n);
    153   }
    154  
    155   /**************************************************************************************
    156   **
    157   ***************************************************************************************/
    158   void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
    159   {
     153}
     154
     155/**************************************************************************************
     156**
     157***************************************************************************************/
     158void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
     159{
    160160    ISInit();
    161161    telescope->ISNewText(dev, name, texts, names, n);
    162   }
    163  
    164   /**************************************************************************************
    165   **
    166   ***************************************************************************************/
    167   void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
    168   {
     162}
     163
     164/**************************************************************************************
     165**
     166***************************************************************************************/
     167void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
     168{
    169169    ISInit();
    170170    telescope->ISNewNumber(dev, name, values, names, n);
    171   }
    172  
    173   /**************************************************************************************
    174   **
    175   ***************************************************************************************/
    176   void ISPoll (void *p)
    177   {
     171}
     172
     173/**************************************************************************************
     174**
     175***************************************************************************************/
     176void ISPoll (void *p)
     177{
    178178    INDI_UNUSED(p);
    179    
     179
    180180    telescope->ISPoll();
    181181    IEAddTimer (POLLMS, ISPoll, NULL);
    182   }
    183  
    184  
    185   /**************************************************************************************
    186   **
    187   ***************************************************************************************/
    188   void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
    189   {
     182}
     183
     184
     185/**************************************************************************************
     186**
     187***************************************************************************************/
     188void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
     189{
    190190    INDI_UNUSED(dev);
    191191    INDI_UNUSED(name);
     
    196196    INDI_UNUSED(names);
    197197    INDI_UNUSED(n);
    198   }
    199  
    200   /**************************************************************************************
    201   **
    202   ***************************************************************************************/
    203   void ISSnoopDevice (XMLEle *root)
    204   {
     198}
     199
     200/**************************************************************************************
     201**
     202***************************************************************************************/
     203void ISSnoopDevice (XMLEle *root)
     204{
    205205    INDI_UNUSED(root);
    206   }
    207  
    208   /**************************************************************************************
    209   ** Initialisation de la classe BAO
    210   ***************************************************************************************/
    211   BAO::BAO()
    212   {
     206}
     207
     208/**************************************************************************************
     209** Initialisation de la classe BAO
     210***************************************************************************************/
     211BAO::BAO()
     212{
    213213    init_properties();
    214    
     214
    215215    ConnectSP.s = IPS_IDLE;
    216    
     216
    217217    lastSet        = -1;
    218218    fd             = -1;
     
    222222    currentSet     = 0;
    223223    JJAnc          = 0.0;
    224    
     224
    225225    SocketsNumber  = 1;
    226    
     226
    227227    ActualisationTM1 = 15.0*60.0;
    228    
     228
    229229    ActualisationTM2 = 5.0;
    230    
     230
    231231    InitThreadOK=false;
    232232    LecturePosition=false;
     
    235235    Goto=false;
    236236    LastGotoOK=true;
    237    
     237
    238238    TrackingMode=1;
    239    
     239
    240240    for (int i=0; i<MAXHOSTNAME; i++)
    241241    {
    242       Sockets[i].Connected=false;
    243       Sockets[i].IP="";
    244     }
    245    
     242        Sockets[i].Connected=false;
     243        Sockets[i].IP="";
     244    }
     245
    246246    InitAntennes();
    247    
    248    
     247
     248
    249249    IDLog("Initilizing from BAO device...\n");
    250     IDLog("Driver Version: 2010-05-12\n");
    251    
     250    IDLog("Driver Version: 2010-11-10\n");
     251
    252252    //enableSimulation(true);
    253   }
    254  
    255   /**************************************************************************************
    256   **
    257   ***************************************************************************************/
    258   BAO::~BAO()
    259   {
    260    
    261   }
    262  
    263   /**************************************************************************************
    264   ** Initialisation des boutons et des zones d'affichage dans la boîte de dialogue INDI
    265   ***************************************************************************************/
    266   void BAO::init_properties()
    267   {
     253}
     254
     255/**************************************************************************************
     256**
     257***************************************************************************************/
     258BAO::~BAO()
     259{
     260
     261}
     262
     263/**************************************************************************************
     264** Initialisation des boutons et des zones d'affichage dans la boîte de dialogue INDI
     265***************************************************************************************/
     266void BAO::init_properties()
     267{
    268268    // Connection
    269269    IUFillSwitch(&ConnectS[0], "CONNECT", "Connect", ISS_OFF);
    270270    IUFillSwitch(&ConnectS[1], "DISCONNECT", "Disconnect", ISS_ON);
    271271    IUFillSwitchVector(&ConnectSP, ConnectS, NARRAY(ConnectS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
    272    
     272
    273273    // Coord Set
    274274    IUFillSwitch(&OnCoordSetS[0], "TRANSIT", "Transit", ISS_ON);
    275275    IUFillSwitch(&OnCoordSetS[1], "TRACKING", "Tracking", ISS_OFF);
    276276    IUFillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
    277    
     277
    278278    // Abort
    279279    IUFillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
    280280    IUFillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
    281    
     281
    282282    // Park
    283283    IUFillSwitch(&ParkS[0], "PARK", "Park", ISS_OFF);
    284284    IUFillSwitchVector(&ParkSP, ParkS, NARRAY(ParkS), mydev, "", "Park", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
    285    
     285
    286286    // Object Name
    287287    IUFillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
    288288    IUFillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
    289    
    290    
     289
     290
    291291    // Equatorial Coords - SET
    292292    IUFillNumber(&EquatorialCoordsWN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
    293293    IUFillNumber(&EquatorialCoordsWN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
    294294    IUFillNumberVector(&EquatorialCoordsWNP, EquatorialCoordsWN, NARRAY(EquatorialCoordsWN), mydev, "EQUATORIAL_EOD_COORD_REQUEST" , "Equatorial JNow", BASIC_GROUP, IP_WO, 0, IPS_IDLE);
    295    
     295
    296296    // Equatorial Coords - READ
    297297    //    IUFillNumber(&EquatorialCoordsRN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
    298298    //    IUFillNumber(&EquatorialCoordsRN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
    299299    //    IUFillNumberVector(&EquatorialCoordsRNP, EquatorialCoordsRN, NARRAY(EquatorialCoordsRN), mydev, "EQUATORIAL_EOD_COORD" , "Equatorial JNow", BASIC_GROUP, IP_RO, 0, IPS_IDLE);
    300    
     300
    301301    // Geographic coord - SET
    302302    IUFillNumber(&GeographicCoordsWN[0], "LAT", "Lat  D", "%10.6m",  -90., 90., 0., 0.);
    303303    IUFillNumber(&GeographicCoordsWN[1], "LONG", "Long D", "%10.6m", 0., 360., 0., 0.);
    304304    IUFillNumberVector(&GeographicCoordsWNP, GeographicCoordsWN, NARRAY(GeographicCoordsWN), mydev, "GEOGRAPHIC_COORD" , "Geographic coords", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
    305    
     305
    306306    // Actualisation - SET
    307307    IUFillNumber(&ActualisationN1[0], "DELAY", "Transit mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
    308308    IUFillNumberVector(&ActualisationNP1, ActualisationN1, NARRAY(ActualisationN1), mydev, "DELAY1" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
    309    
     309
    310310    IUFillNumber(&ActualisationN2[0], "DELAY", "Tracking mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
    311311    IUFillNumberVector(&ActualisationNP2, ActualisationN2, NARRAY(ActualisationN2), mydev, "DELAY2" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
    312    
     312
    313313    // Transit threshold
    314314    //IUFillNumber(&SlewAccuracyN[0], "TransitRA",  "RA (arcmin)", "%10.6m",  0., 60., 1., 3.0);
    315315    //IUFillNumber(&SlewAccuracyN[1], "TransitDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
    316316    //IUFillNumberVector(&SlewAccuracyNP, SlewAccuracyN, NARRAY(SlewAccuracyN), mydev, "Transit Accuracy", "", OPTIONS_GROUP, IP_RW, 0, IPS_IDLE);
    317    
     317
    318318    // Tracking threshold
    319319    //IUFillNumber(&TrackAccuracyN[0], "TrackingRA", "RA (arcmin)", "%10.6m",  0., 60., 1., 3.0);
    320320    //IUFillNumber(&TrackAccuracyN[1], "TrackingDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
    321321    //IUFillNumberVector(&TrackAccuracyNP, TrackAccuracyN, NARRAY(TrackAccuracyN), mydev, "Tracking Accuracy", "", OPTIONS_GROUP, IP_RW, 0, IPS_IDLE);
    322    
    323   }
    324  
    325   /**************************************************************************************
    326   ** Initialisation de la boîte de dialogue INDI (suite)
    327   ***************************************************************************************/
    328   void BAO::ISGetProperties(const char *dev)
    329   {
    330    
     322
     323}
     324
     325/**************************************************************************************
     326** Initialisation de la boîte de dialogue INDI (suite)
     327***************************************************************************************/
     328void BAO::ISGetProperties(const char *dev)
     329{
     330
    331331    if (dev && strcmp (mydev, dev))
    332       return;
    333    
     332        return;
     333
    334334    // Main Control
    335335    IDDefSwitch(&ConnectSP, NULL);
     
    341341    IDDefSwitch(&AbortSlewSP, NULL);
    342342    IDDefSwitch(&ParkSP, NULL);
    343    
     343
    344344    // Options
    345345    //IDDefNumber(&SlewAccuracyNP, NULL);
    346     //IDDefNumber(&TrackAccuracyNP, NULL);   
     346    //IDDefNumber(&TrackAccuracyNP, NULL);
    347347    IDDefNumber(&ActualisationNP1, NULL);
    348348    IDDefNumber(&ActualisationNP2, NULL);
    349    
    350   }
    351  
    352   /**************************************************************************************
    353   ** En cas de changement de texte dans la boîte de dialogue
    354   ***************************************************************************************/
    355   void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
    356   {
     349
     350}
     351
     352/**************************************************************************************
     353** En cas de changement de texte dans la boîte de dialogue
     354***************************************************************************************/
     355void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
     356{
    357357    // Ignore if not ours
    358358    if (strcmp (dev, mydev))
    359       return;
    360    
     359        return;
     360
    361361    if (is_connected() == false)
    362362    {
    363       IDMessage(mydev, "BAORadio. Please connect before issuing any commands.");
    364       reset_all_properties();
    365       return;
    366     }
    367    
     363        IDMessage(mydev, "Error ! Please connect before issuing any commands.");
     364        reset_all_properties();
     365        return;
     366    }
     367
    368368    // ===================================
    369369    // Object Name
     
    371371    if (!strcmp (name, ObjectTP.name))
    372372    {
    373       if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
    374         return;
    375      
    376       ObjectTP.s = IPS_OK;
    377       IDSetText(&ObjectTP, NULL);
    378       return;
    379     }
    380   }
    381  
    382   /**************************************************************************************
    383   ** En cas de changement d'une valeur numérique dans la boîte de dialogue Indi
    384   ***************************************************************************************/
    385   void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
    386   {
    387    
     373        if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
     374            return;
     375
     376        ObjectTP.s = IPS_OK;
     377        IDSetText(&ObjectTP, NULL);
     378        return;
     379    }
     380}
     381
     382/**************************************************************************************
     383** En cas de changement d'une valeur numérique dans la boîte de dialogue Indi
     384***************************************************************************************/
     385void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
     386{
     387
    388388    // Ignore if not ours
    389389    if (strcmp (dev, mydev))
    390       return;
    391    
     390        return;
     391
    392392    if (is_connected() == false)
    393393    {
    394       IDMessage(mydev, "BAO is offline. Please connect before issuing any commands.");
    395       reset_all_properties();
    396       return;
    397     }
    398    
    399    
     394        IDMessage(mydev, "Error ! BAO is offline. Please connect before issuing any commands.");
     395        reset_all_properties();
     396        return;
     397    }
     398
     399
    400400    // ===================================
    401401    // Geographic  Coords
     
    403403    if (!strcmp (name, GeographicCoordsWNP.name))
    404404    {
    405       int i=0, nset=0, error_code=0;
    406      
    407       Latitude=0.0;
    408       Longitude=0.0;
    409      
    410       for (nset = i = 0; i < n; i++)
    411       {
    412         INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
    413         if (eqp == &GeographicCoordsWN[0])
    414         {
    415           Latitude = values[i];
    416           nset += Latitude >= -90.0 && Latitude <= 90.0;
    417          
    418           Latitude*=Pidiv180;
    419         }
    420         else if (eqp == &GeographicCoordsWN[1])
    421         {
    422           Longitude = values[i];
    423           nset += Longitude >= 0.0 && Longitude <= 360.0;
    424          
    425           Longitude*=-Pidiv180;
    426         }
    427       }
    428      
    429       if (nset == 2)
    430       {
    431         //Vérification
    432         //IDLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
    433        
    434         GeographicCoordsWNP.s = IPS_OK;
    435         IDSetNumber(&GeographicCoordsWNP, NULL);
    436       }
    437       else
    438       {
    439         GeographicCoordsWNP.s = IPS_ALERT;
    440         IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
    441        
    442         Latitude=0.0;
    443         Longitude=0.0;
    444       }
    445      
    446       return;
    447     }
    448    
    449    
     405        int i=0, nset=0, error_code=0;
     406
     407        Latitude=0.0;
     408        Longitude=0.0;
     409
     410        for (nset = i = 0; i < n; i++)
     411        {
     412            INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
     413            if (eqp == &GeographicCoordsWN[0])
     414            {
     415                Latitude = values[i];
     416                nset += Latitude >= -90.0 && Latitude <= 90.0;
     417
     418                Latitude*=Pidiv180;
     419            }
     420            else if (eqp == &GeographicCoordsWN[1])
     421            {
     422                Longitude = values[i];
     423                nset += Longitude >= 0.0 && Longitude <= 360.0;
     424
     425                Longitude*=-Pidiv180;
     426            }
     427        }
     428
     429        if (nset == 2)
     430        {
     431            //Vérification
     432            //IDLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
     433
     434            GeographicCoordsWNP.s = IPS_OK;
     435            IDSetNumber(&GeographicCoordsWNP, NULL);
     436        }
     437        else
     438        {
     439            GeographicCoordsWNP.s = IPS_ALERT;
     440            IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
     441
     442            Latitude=0.0;
     443            Longitude=0.0;
     444        }
     445
     446        return;
     447    }
     448
     449
    450450    // ===================================
    451451    // Equatorial Coords
     
    453453    if (!strcmp (name, EquatorialCoordsWNP.name))
    454454    {
    455       int i=0, nset=0, error_code=0;
    456       double newRA =0, newDEC =0;
    457      
    458       for (nset = i = 0; i < n; i++)
    459       {
    460         INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
    461         if (eqp == &EquatorialCoordsWN[0])
    462         {
    463           newRA = values[i];     
    464           nset += newRA >= 0 && newRA <= 24.0;
    465         }
    466         else if (eqp == &EquatorialCoordsWN[1])
    467         {
    468           newDEC = values[i];
    469           nset += newDEC >= -90.0 && newDEC <= 90.0;
    470         }
    471       }
    472      
    473       targetRA  = newRA;
    474       targetDEC = newDEC;
    475      
    476       if (nset == 2)
    477       {
    478         char RAStr[32], DecStr[32];
    479         double targetAZ, targetAlt;
    480        
    481         fs_sexa(RAStr, newRA, 2, 3600);
    482         fs_sexa(DecStr, newDEC, 2, 3600);
    483        
    484         IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
    485        
    486         // on convertit les coordonnées équatoriales de la zone du ciel observée
    487         // en unités de codeurs des moteurs
    488        
    489         ADDEC2Motor(newRA, newDEC);
    490        
    491         if (process_coords() == false)
    492         {
    493           EquatorialCoordsWNP.s = IPS_ALERT;
    494           IDSetNumber(&EquatorialCoordsWNP, NULL);
    495         }
    496       }
    497       else
    498       {
    499         EquatorialCoordsWNP.s = IPS_ALERT;
    500         IDSetNumber(&EquatorialCoordsWNP, "RA or Dec missing or invalid");
    501       }
    502      
    503       return;
    504     }
    505      
     455        int i=0, nset=0, error_code=0;
     456        double newRA =0, newDEC =0;
     457
     458        for (nset = i = 0; i < n; i++)
     459        {
     460            INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
     461            if (eqp == &EquatorialCoordsWN[0])
     462            {
     463                newRA = values[i];
     464                nset += newRA >= 0 && newRA <= 24.0;
     465            }
     466            else if (eqp == &EquatorialCoordsWN[1])
     467            {
     468                newDEC = values[i];
     469                nset += newDEC >= -90.0 && newDEC <= 90.0;
     470            }
     471        }
     472
     473        targetRA  = newRA;
     474        targetDEC = newDEC;
     475
     476        if (nset == 2)
     477        {
     478            char RAStr[32], DecStr[32];
     479            double targetAZ, targetAlt;
     480
     481            fs_sexa(RAStr, newRA, 2, 3600);
     482            fs_sexa(DecStr, newDEC, 2, 3600);
     483
     484            IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
     485
     486            // on convertit les coordonnées équatoriales de la zone du ciel observée
     487            // en unités de codeurs des moteurs
     488
     489            ADDEC2Motor(newRA, newDEC);
     490
     491            if (process_coords() == false)
     492            {
     493                EquatorialCoordsWNP.s = IPS_ALERT;
     494                IDSetNumber(&EquatorialCoordsWNP, NULL);
     495            }
     496        }
     497        else
     498        {
     499            EquatorialCoordsWNP.s = IPS_ALERT;
     500            IDSetNumber(&EquatorialCoordsWNP, "Error ! RA or Dec missing or invalid");
     501        }
     502
     503        return;
     504    }
     505
    506506    // ===================================
    507507    // Actualisation
     
    509509    if (!strcmp (name, ActualisationNP1.name))
    510510    {
    511       int i=0, nset=0, error_code=0;
    512       double newAct1 =0;
    513      
    514       for (nset = i = 0; i < n; i++)
    515       {
    516         INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
    517         if (eqp == &ActualisationN1[0])
    518         {
    519           newAct1 = values[i];
    520          
    521           if (newAct1 >= 0.0 && newAct1 <= 3600.0)
    522           {
    523             ActualisationTM1=newAct1;
    524                
    525             ActualisationNP1.s = IPS_OK;
    526             IDSetNumber(&ActualisationNP1, NULL);
    527           }
    528           else
    529           {
    530             ActualisationNP1.s = IPS_ALERT;
    531             IDSetNumber(&ActualisationNP1, "Delay invalid");
    532           }
    533         }
    534       }
    535      
    536     }
    537    
     511        int i=0, nset=0, error_code=0;
     512        double newAct1 =0;
     513
     514        for (nset = i = 0; i < n; i++)
     515        {
     516            INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
     517            if (eqp == &ActualisationN1[0])
     518            {
     519                newAct1 = values[i];
     520
     521                if (newAct1 >= 0.0 && newAct1 <= 3600.0)
     522                {
     523                    ActualisationTM1=newAct1;
     524
     525                    ActualisationNP1.s = IPS_OK;
     526                    IDSetNumber(&ActualisationNP1, NULL);
     527                }
     528                else
     529                {
     530                    ActualisationNP1.s = IPS_ALERT;
     531                    IDSetNumber(&ActualisationNP1, "Error ! Delay invalid");
     532                }
     533            }
     534        }
     535    }
     536
    538537    if (!strcmp (name, ActualisationNP2.name))
    539538    {
    540       int i=0, nset=0, error_code=0;
    541       double newAct2 =0;
    542      
    543       for (nset = i = 0; i < n; i++)
    544       {
    545         INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
    546         if (eqp == &ActualisationN2[0])
    547         {
    548           newAct2 = values[i];
    549          
    550           if (newAct2 >= 0.0 && newAct2 <= 3600.0)
    551           {
    552             ActualisationTM2=newAct2;
    553                
    554             ActualisationNP2.s = IPS_OK;
    555             IDSetNumber(&ActualisationNP2, NULL);
    556           }
    557           else
    558           {
    559             ActualisationNP2.s = IPS_ALERT;
    560             IDSetNumber(&ActualisationNP2, "Delay invalid");
    561           }
    562         }
    563       }
    564      
     539        int i=0, nset=0, error_code=0;
     540        double newAct2 =0;
     541
     542        for (nset = i = 0; i < n; i++)
     543        {
     544            INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
     545            if (eqp == &ActualisationN2[0])
     546            {
     547                newAct2 = values[i];
     548
     549                if (newAct2 >= 0.0 && newAct2 <= 3600.0)
     550                {
     551                    ActualisationTM2=newAct2;
     552
     553                    ActualisationNP2.s = IPS_OK;
     554                    IDSetNumber(&ActualisationNP2, NULL);
     555                }
     556                else
     557                {
     558                    ActualisationNP2.s = IPS_ALERT;
     559                    IDSetNumber(&ActualisationNP2, "Error ! Delay invalid");
     560                }
     561            }
     562        }
     563
    565564    } /* end EquatorialCoordsWNP */
    566   }
    567  
    568   /**************************************************************************************
    569   ** L'utilisateur clique sur l'un des boutons de la boîte Indi
    570   ***************************************************************************************/
    571   void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
    572   {
     565}
     566
     567/**************************************************************************************
     568** L'utilisateur clique sur l'un des boutons de la boîte Indi
     569***************************************************************************************/
     570void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
     571{
    573572    // ignore if not ours //
    574573    if (strcmp (mydev, dev))
    575       return;
    576    
     574        return;
     575
    577576    // ===================================
    578577    // Connect Switch
     
    580579    if (!strcmp (name, ConnectSP.name))
    581580    {
    582       if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
    583         return;
    584      
    585       connect_telescope();
    586       return;
    587     }
    588    
     581        if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
     582            return;
     583
     584        connect_telescope();
     585        return;
     586    }
     587
    589588    if (is_connected() == false)
    590589    {
    591       IDMessage(mydev, "BAORadio is offline. Please connect before issuing any commands.");
    592       reset_all_properties();
    593       return;
    594     }
    595    
     590        IDMessage(mydev, "Error ! BAORadio is offline. Please connect before issuing any commands.");
     591        reset_all_properties();
     592        return;
     593    }
     594
    596595    // ===================================
    597596    // Coordinate Set
     
    599598    if (!strcmp(name, OnCoordSetSP.name))
    600599    {
    601       if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
    602         return;
    603      
    604       currentSet = get_switch_index(&OnCoordSetSP);
    605       OnCoordSetSP.s = IPS_OK;
    606       IDSetSwitch(&OnCoordSetSP, NULL);
    607     }
    608    
     600        if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
     601            return;
     602
     603        currentSet = get_switch_index(&OnCoordSetSP);
     604        OnCoordSetSP.s = IPS_OK;
     605        IDSetSwitch(&OnCoordSetSP, NULL);
     606    }
     607
    609608    // ===================================
    610609    // Abort slew
     
    612611    if (!strcmp (name, AbortSlewSP.name))
    613612    {
    614       Abort=true;
    615      
    616       IUResetSwitch(&AbortSlewSP);
    617      
    618       /*
    619       if (EquatorialCoordsWNP.s == IPS_BUSY)
    620       {
    621        
    622         AbortSlewSP.s = IPS_OK;
    623         EquatorialCoordsWNP.s       = IPS_IDLE;
    624         EquatorialCoordsRNP.s       = IPS_IDLE;
    625         HorizontalCoordsWNP.s       = IPS_IDLE;
    626         IDSetSwitch(&AbortSlewSP, "Slew aborted.");
    627         IDSetNumber(&EquatorialCoordsWNP, NULL);
    628         IDSetNumber(&EquatorialCoordsRNP, NULL);
    629         IDSetNumber(&HorizontalCoordsWNP, NULL);
    630     }
    631     */
    632       return;
    633     }
    634    
    635    
     613        Abort=true;
     614
     615        IUResetSwitch(&AbortSlewSP);
     616
     617        /*
     618        if (EquatorialCoordsWNP.s == IPS_BUSY)
     619        {
     620
     621        AbortSlewSP.s = IPS_OK;
     622        EquatorialCoordsWNP.s       = IPS_IDLE;
     623        EquatorialCoordsRNP.s       = IPS_IDLE;
     624        HorizontalCoordsWNP.s       = IPS_IDLE;
     625        IDSetSwitch(&AbortSlewSP, "Slew aborted.");
     626        IDSetNumber(&EquatorialCoordsWNP, NULL);
     627        IDSetNumber(&EquatorialCoordsRNP, NULL);
     628        IDSetNumber(&HorizontalCoordsWNP, NULL);
     629        }
     630        */
     631        return;
     632    }
     633
     634
    636635    // ===================================
    637636    // Park
     
    639638    if (!strcmp (name, ParkSP.name))
    640639    {
    641       Park=true;
    642      
    643       IUResetSwitch(&ParkSP);
    644      
    645       /*
    646       if (EquatorialCoordsWNP.s == IPS_BUSY)
    647       {
    648        
    649         AbortSlewSP.s = IPS_OK;
    650         EquatorialCoordsWNP.s       = IPS_IDLE;
    651         EquatorialCoordsRNP.s       = IPS_IDLE;
    652         HorizontalCoordsWNP.s       = IPS_IDLE;
    653         IDSetSwitch(&AbortSlewSP, "Slew aborted.");
    654         IDSetNumber(&EquatorialCoordsWNP, NULL);
    655         IDSetNumber(&EquatorialCoordsRNP, NULL);
    656         IDSetNumber(&HorizontalCoordsWNP, NULL);
    657     }
    658     */
    659       return;
    660     }
    661   }
    662  
    663   /**************************************************************************************
    664   ** fct peut-être inutile
    665   ***************************************************************************************/
    666   void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
    667   {
     640        Park=true;
     641
     642        IUResetSwitch(&ParkSP);
     643
     644        /*
     645        if (EquatorialCoordsWNP.s == IPS_BUSY)
     646        {
     647
     648        AbortSlewSP.s = IPS_OK;
     649        EquatorialCoordsWNP.s       = IPS_IDLE;
     650        EquatorialCoordsRNP.s       = IPS_IDLE;
     651        HorizontalCoordsWNP.s       = IPS_IDLE;
     652        IDSetSwitch(&AbortSlewSP, "Slew aborted.");
     653        IDSetNumber(&EquatorialCoordsWNP, NULL);
     654        IDSetNumber(&EquatorialCoordsRNP, NULL);
     655        IDSetNumber(&HorizontalCoordsWNP, NULL);
     656        }
     657        */
     658        return;
     659    }
     660}
     661
     662/**************************************************************************************
     663** fct peut-être inutile
     664***************************************************************************************/
     665void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
     666{
    668667    nvp->s = IPS_ALERT;
    669    
     668
    670669    /* If the error is a time out, then the device doesn't support this property */
    671670    if (err == -2)
    672671    {
    673       nvp->s = IPS_ALERT;
    674       IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
     672        nvp->s = IPS_ALERT;
     673        IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
    675674    }
    676675    else
    677       /* Changing property failed, user should retry. */
    678       IDSetNumber( nvp , "%s failed.", msg);
    679    
     676        /* Changing property failed, user should retry. */
     677        IDSetNumber( nvp , "%s failed.", msg);
     678
    680679    fault = true;
    681   }
    682  
    683   /**************************************************************************************
    684   ** Initialisation des vecteurs INDI
    685   ***************************************************************************************/
    686   void BAO::reset_all_properties()
    687   {
     680}
     681
     682/**************************************************************************************
     683** Initialisation des vecteurs INDI
     684***************************************************************************************/
     685void BAO::reset_all_properties()
     686{
    688687    ConnectSP.s                 = IPS_IDLE;
    689688    OnCoordSetSP.s              = IPS_IDLE;
     
    698697    ActualisationNP1.s          = IPS_IDLE;
    699698    ActualisationNP2.s          = IPS_IDLE;
    700    
     699
    701700    IUResetSwitch(&OnCoordSetSP);
    702701    IUResetSwitch(&AbortSlewSP);
    703702    IUResetSwitch(&ParkSP);
    704    
     703
    705704    OnCoordSetS[0].s = ISS_ON;
    706705    ConnectS[0].s = ISS_OFF;
    707706    ConnectS[1].s = ISS_ON;
    708    
     707
    709708    IDSetSwitch(&ConnectSP, NULL);
    710709    IDSetSwitch(&OnCoordSetSP, NULL);
     
    719718    IDSetNumber(&ActualisationNP1, NULL);
    720719    IDSetNumber(&ActualisationNP2, NULL);
    721    
    722   }
    723  
    724   /**************************************************************************************
    725   **
    726   ***************************************************************************************/
    727   void BAO::correct_fault()
    728   {
     720
     721}
     722
     723/**************************************************************************************
     724**
     725***************************************************************************************/
     726void BAO::correct_fault()
     727{
    729728    fault = false;
    730729    IDMessage(mydev, "Telescope is online.");
    731   }
    732  
    733   /**************************************************************************************
    734   **
    735   ***************************************************************************************/
    736   bool BAO::is_connected()
    737   {
     730}
     731
     732/**************************************************************************************
     733**
     734***************************************************************************************/
     735bool BAO::is_connected()
     736{
    738737    if (simulation) return true;
    739    
     738
    740739    // return (ConnectSP.sp[0].s == ISS_ON);
    741740    return (ConnectSP.s == IPS_OK);
    742   }
    743  
    744   /**************************************************************************************
    745   **
    746   ***************************************************************************************/
    747   static void retry_connection(void * p)
    748   {
    749    
    750   }
    751  
    752  
    753   /**************************************************************************************
    754   ** Extraction de la position de l'antenne
    755   ** dans le retour de la commande POS
    756   ** POS/Valeur az/Valeur alt
    757   ***************************************************************************************/
    758  
    759   Position BAO::ExtractPosition(std::string str)
    760   {
     741}
     742
     743/**************************************************************************************
     744**
     745***************************************************************************************/
     746static void retry_connection(void * p)
     747{
     748
     749}
     750
     751
     752/**************************************************************************************
     753** Extraction de la position de l'antenne
     754** dans le retour de la commande POS
     755** POS/Valeur az/Valeur alt
     756***************************************************************************************/
     757
     758Position BAO::ExtractPosition(std::string str)
     759{
    761760    Position result;
    762    
     761
    763762    std::string str2;
    764    
     763
    765764    result.x = -1;
    766765    result.y = -1;
    767    
     766
    768767    int pos = str.find("/");
    769    
     768
    770769    if (pos != string::npos)
    771770    {
    772       str2 = str.substr(pos+1);
    773      
    774       pos = str2.find("/");
    775      
    776       if (pos != string::npos)
    777       {
    778         result.x = atoi(str2.substr(0, pos).c_str());
    779        
    780         result.y = atoi(str2.substr(pos+1).c_str());
    781       }
    782     }
    783    
     771        str2 = str.substr(pos+1);
     772
     773        pos = str2.find("/");
     774
     775        if (pos != string::npos)
     776        {
     777            result.x = atoi(str2.substr(0, pos).c_str());
     778
     779            result.y = atoi(str2.substr(pos+1).c_str());
     780        }
     781    }
     782
    784783    return result;
    785   }
    786  
    787  
    788  
    789   /************************************************************************************
    790   * cette procédure convertit les coordonnées equatoriales de l'objet visé
    791   * en unités de codeurs des paraboles (nb de tours des deux axes moteurs depuis la position PARK)
    792   ************************************************************************************/
    793   void BAO::ADDEC2Motor(double newRA, double newDEC)
    794   {
     784}
     785
     786
     787
     788/************************************************************************************
     789* cette procédure convertit les coordonnées equatoriales de l'objet visé
     790* en unités de codeurs des paraboles (nb de tours des deux axes moteurs depuis la position PARK)
     791************************************************************************************/
     792void BAO::ADDEC2Motor(double newRA, double newDEC)
     793{
    795794    double targetAz;
    796795    double targetAlt;
    797796    char AzStr[32];
    798797    char AltStr[32];
    799    
     798
    800799    // Calcule la hauteur et l'azimut de la zone du ciel pointée (en fonction de la date et du lieu)
    801    
     800
    802801    Azimut(tsl, Latitude, newRA * 15.0 * Pidiv180, newDEC * Pidiv180, &targetAz, &targetAlt);
    803    
     802
    804803    // En degrés
    805    
     804
    806805    targetAlt *= N180divPi;
    807806    targetAz *= N180divPi;
    808    
     807
    809808    // Affichage dans les logs
    810    
     809
    811810    fs_sexa(AzStr, targetAz, 2, 3600);
    812811    fs_sexa(AltStr, targetAlt, 2, 3600);
    813    
     812
    814813    IDLog("Horizontal coords : az %s - Alt %s\n", AzStr, AltStr);
    815    
     814
    816815    // Le calcul est ici trÚs sommaire et arbitraire :
    817816    // Je considÚre qu'il y a 100 positions possibles sur les deux axes
    818817    // De plus, je considÚre qu'il n'est pas possible de viser un objet à
    819818    // moins de 30° de hauteur au-dessus de l'horizon
    820    
     819
    821820    TargetPosition.x=(int)(targetAz*100.0/360.0);
    822    
     821
    823822    targetAlt=((90.0-targetAlt)/60.0);
    824    
    825     if (targetAlt>=1.0) 
    826     {
    827           targetAlt=1.0; //on ne peut pas viser un objet situé à moins de 30°
    828           //au-dessus de l'horizon
    829          
    830           IDSetSwitch(&OnCoordSetSP, "Erreur : l objet suivi est situé à moins de 30° en-dessus de l horizon. Goto annulé.");
    831          
    832           Goto=false;
    833          
    834           LecturePosition=false;
    835        
    836           InitAntennes();
    837     }
    838  
     823
     824    if (targetAlt>=1.0)
     825    {
     826        targetAlt=1.0; //on ne peut pas viser un objet situé à moins de 30°
     827        //au-dessus de l'horizon
     828
     829        IDSetSwitch(&OnCoordSetSP, "Erreur ! L objet suivi est situe a moins de 30° au-dessus de l horizon. Goto annule.");
     830
     831        Goto=false;
     832
     833        LecturePosition=false;
     834
     835        InitAntennes();
     836    }
     837
    839838    TargetPosition.y=(int)(100.0*targetAlt);
    840   }
    841  
    842  
    843   /************************************************************************************
    844   * Retourne simplement le nombre d'antennes connectées
    845   * et capables de communiquer
    846   ************************************************************************************/
    847  
    848   int BAO::AntennesConnectees()
    849   {
     839}
     840
     841
     842/************************************************************************************
     843* Retourne simplement le nombre d'antennes connectées
     844* et capables de communiquer
     845************************************************************************************/
     846
     847int BAO::AntennesConnectees()
     848{
    850849    int num=0;
    851    
     850
    852851    for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected) num++;
    853    
     852
    854853    return num;
    855   }
    856  
    857  
    858   /************************************************************************************
    859   * Initialisation des paramÚtres des antennes
    860   *
    861   ************************************************************************************/
    862   void BAO::InitAntennes()
    863   {
     854}
     855
     856
     857/************************************************************************************
     858* Initialisation des paramÚtres des antennes
     859*
     860************************************************************************************/
     861void BAO::InitAntennes()
     862{
    864863    for (int i=0; i < MAXHOSTNAME ; i++)
    865864    {
    866       Sockets[i].status=0;
    867       Sockets[i].sendalertes=0;
    868       Sockets[i].AttenteExecution=0;
    869       Sockets[i].AnomaliesExecution=0;
    870       Sockets[i].etape=0;
    871      
    872       Sockets[i].ack_status=false;
    873       Sockets[i].ack_pos=false;
    874       Sockets[i].ack_park=false;
    875       Sockets[i].ack_abort=false;
    876       Sockets[i].ack_goto=false;
    877      
    878       Sockets[i].PosValides=false;
    879       Sockets[i].GotoOk=false;
    880     }
    881   }
    882  
    883  
    884   /**************************************************************************************
    885   ** Procédure principale
    886   ** Elle est appelée toutes les POLLMS ms (ici 1 ms)
    887   ***************************************************************************************/
    888   void BAO::ISPoll()
    889   {
     865        Sockets[i].status=0;
     866        Sockets[i].sendalertes=0;
     867        Sockets[i].AttenteExecution=0;
     868        Sockets[i].AnomaliesExecution=0;
     869        Sockets[i].etape=0;
     870
     871        Sockets[i].ack_status=false;
     872        Sockets[i].ack_pos=false;
     873        Sockets[i].ack_park=false;
     874        Sockets[i].ack_abort=false;
     875        Sockets[i].ack_goto=false;
     876
     877        Sockets[i].PosValides=false;
     878        Sockets[i].GotoOk=false;
     879    }
     880}
     881
     882
     883/**************************************************************************************
     884** Procédure principale
     885** Elle est appelée toutes les POLLMS ms (ici 1 ms)
     886***************************************************************************************/
     887void BAO::ISPoll()
     888{
    890889    static bool ISPOLLRunning=false;
    891890    static int memSocketsNumber=-1;
    892891    static unsigned int compt=100;
    893    
     892
    894893    int pos;
    895    
     894
    896895    struct tm date;
    897896    time_t t;
    898897    struct timeval tv;
    899898    struct timezone tz;
    900    
     899
    901900    if (is_connected() == false) return;
    902    
     901
    903902    if (ISPOLLRunning) return;
    904    
     903
    905904    ISPOLLRunning=true;
    906    
     905
    907906    compt++;
    908    
    909    
     907
     908
    910909    //toutes les 100 millisec
    911    
     910
    912911    if ( compt%100 == 0)
    913912    {
    914       //Récupération de la date et de l'heure
    915      
    916       time(&t);
    917       date=*gmtime(&t);
    918       gettimeofday(&tv, &tz);
    919      
    920       Annee=(double)(date.tm_year+1900);
    921       Mois=(double)(date.tm_mon+1);
    922       Jour=(double)date.tm_mday;
    923       Heu=(double)date.tm_hour;
    924       Min=(double)date.tm_min;
    925       Sec=(double)date.tm_sec+tv.tv_usec/1.0E6;
    926       UTCP=0.0;//(double)date.tm_isdst;
    927      
    928      
    929       //Calcul du temps sidéral local
    930      
    931       CalculTSL();
    932      
    933      
    934       //Y a-t-il de nouvelles tentatives de connexion sur le serveur ?
    935      
    936       InitThread();         
    937     }
    938    
    939    
    940    
    941    
     913        //Récupération de la date et de l'heure
     914
     915        time(&t);
     916        date=*gmtime(&t);
     917        gettimeofday(&tv, &tz);
     918
     919        Annee=(double)(date.tm_year+1900);
     920        Mois=(double)(date.tm_mon+1);
     921        Jour=(double)date.tm_mday;
     922        Heu=(double)date.tm_hour;
     923        Min=(double)date.tm_min;
     924        Sec=(double)date.tm_sec+tv.tv_usec/1.0E6;
     925        UTCP=0.0;//(double)date.tm_isdst;
     926
     927
     928        //Calcul du temps sidéral local
     929
     930        CalculTSL();
     931
     932
     933        //Y a-t-il de nouvelles tentatives de connexion sur le serveur ?
     934
     935        InitThread();
     936    }
     937
     938
     939
     940
    942941    if (InitThreadOK)  // Il faut qu'il y ait eu au moins une connexion détectée par le thread pour continuer
    943942    {
    944      
    945       // Nouvelle connexion sur le socket !
    946      
    947       if (SocketsNumber>memSocketsNumber)
    948       {
    949         memSocketsNumber=SocketsNumber;
    950        
    951         IDSetSwitch(&ConnectSP, "Connexion de l antenne %s. (Antennes connectées : %i)",
    952                     Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
    953       }
    954      
    955      
    956      
    957       // Début des échanges avec les microcontrÃŽleurs
    958      
    959       // Analyse des réponses des microcontrÃŽleurs
    960      
    961       for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
    962       {
    963         try
    964         {
    965           std::string reponse, memreponse;
    966           // on récupÚre la réponse du microcontrÃŽleur
    967          
    968           Sockets[i].new_sock >> reponse;
    969          
    970           //IDSetSwitch(&OnCoordSetSP, "Réponse ISPOLL : %s\n", reponse.c_str());        // pour vérif
    971          
    972           //Dans le cas où plusieurs trames seraient arrivées entre deux appels de POLLMS
    973           //les traiter successivement
    974          
    975           pos=reponse.find("\n");   // d'où l'intérêt de mettre un '\n' à la fin des trames
    976           //pour différencier une trame de la précédente
    977           while ((pos!=string::npos) && (reponse.length()>1))
    978           {
    979             memreponse=reponse.substr(pos+1);
    980            
    981             reponse=reponse.substr(0, pos);
    982            
    983            
    984             // On traite ici les acknowledges
    985            
    986             if ((reponse.find("ACK")!=string::npos) && (reponse.find("NACK")==string::npos))
    987             {         
    988               if (reponse.find("POS")!=string::npos)
    989               {
    990                 Sockets[i].ack_pos=true;
    991               }
    992               else if (reponse.find("GOTO")!=string::npos)
    993               {
    994                 Sockets[i].ack_goto=true;
    995               }
    996               else if (reponse.find("PARK")!=string::npos)
    997               {
    998                 Sockets[i].ack_park=true;
    999               }
    1000               else if (reponse.find("ABORT")!=string::npos)
    1001               {
    1002                 Sockets[i].ack_abort=true;
    1003               }
    1004             }
    1005             else
    1006             {
    1007              
    1008               //réponse à la requête POSITION
    1009               if (reponse.find("POS")!=string::npos)
    1010               {
    1011                 if (reponse.find("NACK")!=string::npos)
    1012                 {
    1013                   OnCoordSetSP.s = IPS_ALERT;
    1014                   IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
    1015                               Sockets[i].IP.c_str());
    1016                               Sockets[i].PosValides=false;
    1017                               // Si la position de l'antenne est inconnue, on déconnecte l'antenne
    1018                               Sockets[i].Connected=false;
    1019                 }
    1020                 else if (Sockets[i].ack_pos)
    1021                 {
    1022                   OnCoordSetSP.s = IPS_OK;
    1023                   Sockets[i].Pos = ExtractPosition(reponse);
    1024                   Sockets[i].PosValides = true;
    1025                   IDSetSwitch(&ParkSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
    1026                     Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
    1027                 }
    1028                
    1029               }//réponse à la requête PARK
    1030               else if (reponse.find("PARK")!=string::npos)
    1031               {
    1032                 if (reponse.find("NACK")!=string::npos)
    1033                 {
    1034                   ParkSP.s = IPS_ALERT;
    1035                   IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
    1036                 }
    1037                 else if (reponse.find("OK")!=string::npos)
    1038                 {
    1039                   ParkSP.s = IPS_OK;
    1040                   IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
    1041                 }
    1042                
    1043               }//réponse à la requête ABORT
    1044               else if (reponse.find("ABORT")!=string::npos)
    1045               {
    1046                 if (reponse.find("NACK")!=string::npos)
    1047                 {
    1048                   AbortSlewSP.s = IPS_ALERT;
    1049                   IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
    1050                 }
    1051                
    1052                 if (reponse.find("OK")!=string::npos)
    1053                 {
    1054                   AbortSlewSP.s = IPS_OK;
    1055                   IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
    1056                 }
    1057                
    1058               } //réponse à la requête GOTO
    1059               else if (reponse.find("GOTO")!=string::npos)
    1060               {
    1061                 if (reponse.find("NACK")!=string::npos)
    1062                 {
    1063                   OnCoordSetSP.s = IPS_ALERT;
    1064                   IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur GOTO !\n",  Sockets[i].IP.c_str());
    1065                   Sockets[i].Connected=false;
    1066                 }
    1067                 else if (Sockets[i].ack_goto)
    1068                 {
    1069                   if (reponse.find("OK")!=string::npos)
    1070                   {
    1071                     OnCoordSetSP.s = IPS_OK;
    1072                  
    1073                     Sockets[i].GotoOk=true;
    1074                  
    1075                     IDSetSwitch(&ParkSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
    1076                  
    1077                     lastRA  = targetRA;
    1078                     lastDEC = targetDEC;
    1079                  
    1080                      //IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);*/
    1081                  
    1082                     EquatorialCoordsWNP.s = IPS_OK;
    1083                     IDSetNumber (&EquatorialCoordsWNP, NULL);
    1084                  
    1085                     // Fin du Goto pour toutes les antennes ?
    1086                  
    1087                     int num=0;
    1088                  
    1089                     for (int j=1; j<SocketsNumber; j++) if (Sockets[j].Connected)
    1090                     {
    1091                       if (Sockets[j].GotoOk) num++;
    1092                     }
    1093                  
    1094                     if ((num == AntennesConnectees()) && (num>0))
    1095                     {
    1096                       LecturePosition=false;
    1097                    
    1098                       InitAntennes();
    1099                      
    1100                       LastGotoOK=true;
    1101                    
    1102                       IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
    1103                     }
    1104                   } 
    1105                 }
    1106               }
    1107             }
    1108            
    1109             // On passe éventuellement à la trame suivante
    1110            
    1111             reponse=memreponse;
    1112             pos=reponse.find("\n");
    1113            
    1114           }
    1115         }
    1116         catch (SocketException& e) //Aïe
    1117         {
    1118           Sockets[i].new_sock.shutdown();
    1119           Sockets[i].new_sock.create();
    1120           Sockets[i].Connected = Sockets[i].new_sock.connect((std::string)Sockets[i].IP);
    1121          
    1122           if (Sockets[i].Connected)
    1123           {
    1124             Sockets[i].AttenteExecution=0;
    1125             Sockets[i].AnomaliesExecution=0;
    1126           } 
    1127          
    1128           std::string oss;
    1129           oss="SocketException IsPoll : " + e.description() + "\n";
    1130           size_t size = oss.size() + 1;
    1131           char* buffer = new char[size];
    1132           strncpy(buffer, oss.c_str(), size);
    1133           IDLog(buffer);
    1134           delete [] buffer;
    1135         }
    1136       }
    1137      
    1138      
    1139      
    1140       if (Abort)
    1141       {
    1142         IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
    1143        
    1144         Goto=false;
    1145        
    1146         for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
    1147         {
    1148           if (!ABORT(i)) Sockets[i].sendalertes++;
    1149         }
    1150        
    1151         LecturePosition=false;
    1152        
    1153         InitAntennes();
    1154        
    1155         Abort=false;
    1156       }
    1157      
    1158      
    1159       if (Park)
    1160       {
    1161         IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
    1162        
    1163         Goto=false;
    1164        
    1165         for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
    1166         {
    1167           if (!PARK(i)) Sockets[i].sendalertes++;
    1168         }
    1169        
    1170         LecturePosition=false;
    1171        
    1172         InitAntennes();
    1173        
    1174         Park=false;
    1175       }
    1176      
    1177      
    1178       // Gestion du suivi
    1179      
    1180       if ((Goto) && (LastGotoOK))
    1181       {
    1182         // Durée entre deux actualisations
    1183        
    1184         double delai=ActualisationTM1/3600.0/24.0;   // Actualisation toutes les 15 minutes en mode transit
    1185        
    1186         if (TrackingMode==2) delai=ActualisationTM2/3600.0/24.0;   //et 5 secs en mode tracking
    1187          
    1188          
    1189           // On actualise la position
    1190          
    1191           if (JJ-JJAnc > delai)
    1192           {
    1193            
    1194             LastGotoOK=false;
    1195            
    1196             LecturePosition=true;
    1197            
    1198             ADDEC2Motor(targetRA, targetDEC);
    1199            
    1200             InitAntennes();         
    1201            
    1202             JJAnc=JJ;
    1203           }
    1204          
    1205           //Plus d'antenne !
    1206          
    1207           if (AntennesConnectees() == 0)
    1208           {
    1209             // LecturePosition=false;
    1210            
    1211             // Goto=false;
    1212            
    1213             // InitAntennes();
    1214            
    1215             if ( compt % 1000 == 0)  IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectées !");
    1216           }
    1217       }
    1218      
    1219      
    1220      
    1221       // Exécution de la procédure complÚte de lecture de la position de l'antenne
    1222       // puis envoi d'une commande Goto
    1223      
    1224       if (LecturePosition)
    1225       {
    1226         for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
    1227         {
    1228           switch (Sockets[i].etape)
    1229           {
    1230            
    1231             //Envoi de la commande POS
    1232             case 0 :
    1233             {
    1234               Sockets[i].ack_pos=false;
    1235               Sockets[i].PosValides=false;
    1236              
    1237               if (!POSITION(i)) Sockets[i].sendalertes++;
    1238              
    1239               Sockets[i].etape++;
    1240             }
    1241             break;
    1242            
    1243             //ack POS
    1244             case 1 :
    1245             {
    1246               if (Sockets[i].ack_pos)
    1247               {
    1248                 Sockets[i].AttenteExecution=0;
    1249                 Sockets[i].AnomaliesExecution=0;
    1250                 Sockets[i].etape++;
    1251                 i--;
    1252               }
    1253               else
    1254               {
    1255                 // on réitÚre l'ordre précédent si rien ne se passe
    1256                
    1257                 Sockets[i].AttenteExecution++;
    1258                
    1259                 if (Sockets[i].AttenteExecution>MAXATTENTE)
    1260                 {
    1261                   Sockets[i].etape=0;
    1262                   Sockets[i].AttenteExecution=0;
    1263                   Sockets[i].AnomaliesExecution++;
    1264                 }
    1265                
    1266                 if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
    1267                 {
    1268                   Sockets[i].etape=3;
    1269                  
    1270                  // if ( compt % 1000 == 0)
    1271                   {
    1272                     IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. Pas d acknowledge reçu aprÚs l ordre POSITION. Déconnexion de l antenne.",
    1273                                 Sockets[i].IP.c_str());
    1274                                 Sockets[i].Connected=false;
    1275                   }
    1276                 }
    1277               }
    1278             }
    1279             break;
    1280            
    1281             //Valeurs pos valides ?
    1282             case 2 :
    1283             {
    1284               if (Sockets[i].PosValides)
    1285               {
    1286                 Sockets[i].AttenteExecution=0;
    1287                 Sockets[i].etape++;
    1288               }
    1289               else
    1290               {
    1291                 // on réitÚre l'ordre précédent si rien ne se passe
    1292                
    1293                 Sockets[i].AttenteExecution++;
    1294                
    1295                 if (Sockets[i].AttenteExecution>MAXATTENTE)
    1296                 {
    1297                   Sockets[i].etape=2;
    1298                   Sockets[i].AttenteExecution=0;
    1299                   Sockets[i].AnomaliesExecution++;
    1300                 }
    1301                
    1302                 if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
    1303                 {
    1304                   Sockets[i].etape=3;
    1305                  
    1306                  // if ( compt % 1000 == 0)
    1307                   {
    1308                     IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. La position retournée n est pas valide. Déconnexion de l antenne.",
    1309                                 Sockets[i].IP.c_str());
    1310                                 Sockets[i].Connected=false;
    1311                   }
    1312                 }
    1313               }
    1314             }
    1315             break;
    1316            
    1317             //ack goto  ?
    1318             case 4 :
    1319             {
    1320               if (Sockets[i].ack_goto)
    1321               {
    1322                 Sockets[i].AttenteExecution=0;
    1323                 Sockets[i].AnomaliesExecution=0;
    1324                 Sockets[i].etape++;
    1325               }
    1326               else
    1327               {
    1328                 // on réitÚre l'ordre précédent si rien ne se passe
    1329                
    1330                 Sockets[i].AttenteExecution++;
    1331                
    1332                 if (Sockets[i].AttenteExecution>MAXATTENTE)
    1333                 {
    1334                   Sockets[i].etape=4;
    1335                   Sockets[i].AttenteExecution=0;
    1336                   Sockets[i].AnomaliesExecution++;
    1337                 }
    1338                
    1339                 if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
    1340                 {
    1341                   Sockets[i].etape=6;
    1342                  
    1343                  // if ( compt % 1000 == 0)
    1344                   {
    1345                     IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. Pas d acknowledge reçu aprÚs l ordre GOTO. Déconnexion de l antenne.",
    1346                                 Sockets[i].IP.c_str());
    1347                                 Sockets[i].Connected=false;
    1348                   }
    1349                 }
    1350               }
    1351             }
    1352             break;
    1353            
    1354             //goto ok  ?
    1355             case 5 :
    1356             {
    1357               if (Sockets[i].GotoOk)
    1358               {
    1359                 Sockets[i].AttenteExecution=0;
    1360                 Sockets[i].AnomaliesExecution=0;
    1361                 Sockets[i].etape++;
    1362               }
    1363               else
    1364               {
    1365                 // on réitÚre l'ordre précédent si rien ne se passe
    1366                
    1367                 Sockets[i].AttenteExecution++;
    1368                
    1369                 if (Sockets[i].AttenteExecution>MAXATTENTE)
    1370                 {
    1371                   Sockets[i].etape=5;
    1372                   Sockets[i].AttenteExecution=0;
    1373                   Sockets[i].AnomaliesExecution++;
    1374                 }
    1375                
    1376                 if (Sockets[i].AnomaliesExecution>MAXANOMALIESGOTO)
    1377                 {
    1378                   Sockets[i].etape=6;
    1379                  
    1380                  // if ( compt % 1000 == 0)
    1381                   {
    1382                     IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. L antenne n a pas renvoyé GOTO/OK. Déconnexion de l antenne.",
    1383                                 Sockets[i].IP.c_str());
    1384                                 Sockets[i].Connected=false;
    1385                                
    1386                                
    1387                   }
    1388                 }
    1389               }
    1390             }
    1391             break;
    1392            
    1393           }
    1394         }
    1395       }
    1396      
    1397      
    1398      
    1399      
    1400      
    1401      
    1402       // Détection d'anomalies concernant l'envoi de trames sur la socket. déconnexion du micro-cont ?
    1403      
    1404       for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
    1405       {
    1406         if (Sockets[i].sendalertes > 0)
    1407         {
    1408           Sockets[i].etape=5;
    1409          
    1410         //  if ( compt % 1000 == 0)
    1411           {
    1412             IDSetSwitch(&OnCoordSetSP, "Anomalie détectée sur l antenne %s. Déconnexion de l antenne.",
    1413                         Sockets[i].IP.c_str());
    1414                        
    1415                         Sockets[i].Connected=false;
    1416           }
    1417         }
    1418       }
    1419      
    1420      
    1421      
    1422       //On attend que toutes les antennes soient prêtes pour lancer l'ordre Goto -> meilleure synchronisation
    1423      
    1424       int num=0;
    1425      
    1426       for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
    1427       {
    1428         if (Sockets[i].etape == 3) num++; //fin de la procédure LecturePosition. Les antennes sont prêtes
    1429           //à recevoir l'ordre GOto
    1430       }
    1431      
    1432       if ((num == AntennesConnectees()) && (num>0))
    1433       {
    1434         for (int i=1; i<SocketsNumber; i++ ) if (Sockets[i].Connected)
    1435         {
    1436           Sockets[i].ack_goto=false;
    1437           Sockets[i].AttenteExecution=0;
    1438           Sockets[i].AnomaliesExecution=0;
    1439          
    1440           if (!GOTO(i, Sockets[i].Pos.x - TargetPosition.x, Sockets[i].Pos.y - TargetPosition.y )) Sockets[i].sendalertes++;
    1441          
    1442           Sockets[i].etape++;
    1443         }
    1444       }
    1445      
    1446      
    1447        
    1448     }
    1449    
     943
     944        // Nouvelle connexion sur le socket !
     945
     946        if (SocketsNumber>memSocketsNumber)
     947        {
     948            memSocketsNumber=SocketsNumber;
     949
     950            IDSetSwitch(&ConnectSP, "Connexion de l antenne %s. (Antennes connectees : %i)",
     951                        Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
     952        }
     953
     954
     955
     956        // Début des échanges avec les microcontrÃŽleurs
     957
     958        // Analyse des réponses des microcontrÃŽleurs
     959
     960        for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
     961        {
     962            try
     963            {
     964                std::string reponse, memreponse;
     965                // on récupÚre la réponse du microcontrÃŽleur
     966
     967                Sockets[i].new_sock >> reponse;
     968
     969                //IDSetSwitch(&OnCoordSetSP, "Réponse ISPOLL : %s\n", reponse.c_str());        // pour vérif
     970
     971                //Dans le cas où plusieurs trames seraient arrivées entre deux appels de POLLMS
     972                //les traiter successivement
     973
     974                pos=reponse.find("\n");   // d'où l'intérêt de mettre un '\n' à la fin des trames
     975                //pour différencier une trame de la précédente
     976
     977                while ((pos!=string::npos) && (reponse.length()>1))
     978                {
     979                    memreponse=reponse.substr(pos+1);
     980
     981                    reponse=reponse.substr(0, pos);
     982
     983
     984                    // On traite ici les acknowledges
     985
     986                    if ((reponse.find("ACK")!=string::npos) && (reponse.find("NACK")==string::npos))
     987                    {
     988                        if (reponse.find("POSITION")!=string::npos)
     989                        {
     990                            Sockets[i].ack_pos=true;
     991                        }
     992                        else if (reponse.find("GOTO")!=string::npos)
     993                        {
     994                            Sockets[i].ack_goto=true;
     995                        }
     996                        else if (reponse.find("PARK")!=string::npos)
     997                        {
     998                            Sockets[i].ack_park=true;
     999                        }
     1000                        else if (reponse.find("ABORT")!=string::npos)
     1001                        {
     1002                            Sockets[i].ack_abort=true;
     1003                        }
     1004                    }
     1005                    else
     1006                    {
     1007
     1008                        //réponse à la requête POSITION
     1009                        if (reponse.find("POSITION")!=string::npos)
     1010                        {
     1011                            if (reponse.find("NACK")!=string::npos)
     1012                            {
     1013                                OnCoordSetSP.s = IPS_ALERT;
     1014                                IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
     1015                                            Sockets[i].IP.c_str());
     1016                                Sockets[i].PosValides=false;
     1017                                // Si la position de l'antenne est inconnue, on déconnecte l'antenne
     1018                                Sockets[i].Connected=false;
     1019                            }
     1020                            else if (Sockets[i].ack_pos)
     1021                            {
     1022                                OnCoordSetSP.s = IPS_OK;
     1023                                Sockets[i].Pos = ExtractPosition(reponse);
     1024                                Sockets[i].PosValides = true;
     1025                                IDSetSwitch(&ParkSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
     1026                                            Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
     1027                            }
     1028
     1029                        }//réponse à la requête PARK
     1030                        else if (reponse.find("PARK")!=string::npos)
     1031                        {
     1032                            if (reponse.find("NACK")!=string::npos)
     1033                            {
     1034                                ParkSP.s = IPS_ALERT;
     1035                                IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
     1036                            }
     1037                            else if (reponse.find("OK")!=string::npos)
     1038                            {
     1039                                ParkSP.s = IPS_OK;
     1040                                IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
     1041                            }
     1042
     1043                        }//réponse à la requête ABORT
     1044                        else if (reponse.find("ABORT")!=string::npos)
     1045                        {
     1046                            if (reponse.find("NACK")!=string::npos)
     1047                            {
     1048                                AbortSlewSP.s = IPS_ALERT;
     1049                                IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
     1050                            }
     1051
     1052                            if (reponse.find("OK")!=string::npos)
     1053                            {
     1054                                AbortSlewSP.s = IPS_OK;
     1055                                IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
     1056                            }
     1057
     1058                        } //réponse à la requête GOTO
     1059                        else if (reponse.find("GOTO")!=string::npos)
     1060                        {
     1061                            if (reponse.find("NACK")!=string::npos)
     1062                            {
     1063                                OnCoordSetSP.s = IPS_ALERT;
     1064                                IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur GOTO !\n",  Sockets[i].IP.c_str());
     1065                                Sockets[i].Connected=false;
     1066                            }
     1067                            else if (Sockets[i].ack_goto)
     1068                            {
     1069                                if (reponse.find("OK")!=string::npos)
     1070                                {
     1071                                    OnCoordSetSP.s = IPS_OK;
     1072
     1073                                    Sockets[i].GotoOk=true;
     1074
     1075                                    IDSetSwitch(&ParkSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
     1076
     1077                                    lastRA  = targetRA;
     1078                                    lastDEC = targetDEC;
     1079
     1080                                    //IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);*/
     1081
     1082                                    EquatorialCoordsWNP.s = IPS_OK;
     1083                                    IDSetNumber (&EquatorialCoordsWNP, NULL);
     1084
     1085                                    // Fin du Goto pour toutes les antennes ?
     1086
     1087                                    int num=0;
     1088
     1089                                    for (int j=1; j<SocketsNumber; j++) if (Sockets[j].Connected)
     1090                                        {
     1091                                            if (Sockets[j].GotoOk) num++;
     1092                                        }
     1093
     1094                                    if ((num == AntennesConnectees()) && (num>0))
     1095                                    {
     1096                                        LecturePosition=false;
     1097
     1098                                        InitAntennes();
     1099
     1100                                        LastGotoOK=true;
     1101
     1102                                        IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
     1103                                    }
     1104                                }
     1105                            }
     1106                        }
     1107                    }
     1108
     1109                    // On passe éventuellement à la trame suivante
     1110
     1111                    reponse=memreponse;
     1112                    pos=reponse.find("\n");
     1113
     1114                }
     1115            }
     1116            catch (SocketException& e) //Aïe
     1117            {
     1118                Sockets[i].new_sock.shutdown();
     1119                Sockets[i].new_sock.create();
     1120                Sockets[i].Connected = Sockets[i].new_sock.connect((std::string)Sockets[i].IP);
     1121
     1122                if (Sockets[i].Connected)
     1123                {
     1124                    Sockets[i].AttenteExecution=0;
     1125                    Sockets[i].AnomaliesExecution=0;
     1126                }
     1127
     1128                std::string oss;
     1129                oss="SocketException IsPoll : " + e.description() + "\n";
     1130                size_t size = oss.size() + 1;
     1131                char* buffer = new char[size];
     1132                strncpy(buffer, oss.c_str(), size);
     1133                IDLog(buffer);
     1134                delete [] buffer;
     1135            }
     1136        }
     1137
     1138
     1139
     1140        if (Abort)
     1141        {
     1142            IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
     1143
     1144            Goto=false;
     1145
     1146            for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
     1147                {
     1148                    if (!ABORT(i)) Sockets[i].sendalertes++;
     1149                }
     1150
     1151            LecturePosition=false;
     1152
     1153            InitAntennes();
     1154
     1155            Abort=false;
     1156        }
     1157
     1158
     1159        if (Park)
     1160        {
     1161            IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
     1162
     1163            Goto=false;
     1164
     1165            for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
     1166                {
     1167                    if (!PARK(i)) Sockets[i].sendalertes++;
     1168                }
     1169
     1170            LecturePosition=false;
     1171
     1172            InitAntennes();
     1173
     1174            Park=false;
     1175        }
     1176
     1177
     1178        // Gestion du suivi
     1179
     1180        if ((Goto) && (LastGotoOK))
     1181        {
     1182            // Durée entre deux actualisations
     1183
     1184            double delai=ActualisationTM1/3600.0/24.0;   // Actualisation toutes les 15 minutes en mode transit
     1185
     1186            if (TrackingMode==2) delai=ActualisationTM2/3600.0/24.0;   //et 5 secs en mode tracking
     1187
     1188
     1189            // On actualise la position
     1190
     1191            if (JJ-JJAnc > delai)
     1192            {
     1193
     1194                LastGotoOK=false;
     1195
     1196                LecturePosition=true;
     1197
     1198                ADDEC2Motor(targetRA, targetDEC);
     1199
     1200                InitAntennes();
     1201
     1202                JJAnc=JJ;
     1203            }
     1204
     1205            //Plus d'antenne !
     1206
     1207            if (AntennesConnectees() == 0)
     1208            {
     1209                // LecturePosition=false;
     1210
     1211                // Goto=false;
     1212
     1213                // InitAntennes();
     1214
     1215                if ( compt % 1000 == 0)  IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectees !");
     1216            }
     1217        }
     1218
     1219
     1220
     1221        // Exécution de la procédure complÚte de lecture de la position de l'antenne
     1222        // puis envoi d'une commande Goto
     1223
     1224        if (LecturePosition)
     1225        {
     1226            for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
     1227            {
     1228                switch (Sockets[i].etape)
     1229                {
     1230
     1231                    //Envoi de la commande POS
     1232                case 0 :
     1233                {
     1234                    Sockets[i].ack_pos=false;
     1235                    Sockets[i].PosValides=false;
     1236
     1237                    if (!POSITION(i)) Sockets[i].sendalertes++;
     1238
     1239                    Sockets[i].etape++;
     1240                }
     1241                break;
     1242
     1243                //ack POS
     1244                case 1 :
     1245                {
     1246                    if (Sockets[i].ack_pos)
     1247                    {
     1248                        Sockets[i].AttenteExecution=0;
     1249                        Sockets[i].AnomaliesExecution=0;
     1250                        Sockets[i].etape++;
     1251                        i--;
     1252                    }
     1253                    else
     1254                    {
     1255                        // on réitÚre l'ordre précédent si rien ne se passe
     1256
     1257                        Sockets[i].AttenteExecution++;
     1258
     1259                        if (Sockets[i].AttenteExecution>MAXATTENTE)
     1260                        {
     1261                            Sockets[i].etape=0;
     1262                            Sockets[i].AttenteExecution=0;
     1263                            Sockets[i].AnomaliesExecution++;
     1264                        }
     1265
     1266                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
     1267                        {
     1268                            Sockets[i].etape=3;
     1269
     1270                            // if ( compt % 1000 == 0)
     1271                            {
     1272                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre POSITION. \
     1273                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
     1274                                Sockets[i].Connected=false;
     1275                            }
     1276                        }
     1277                    }
     1278                }
     1279                break;
     1280
     1281                //Valeurs pos valides ?
     1282                case 2 :
     1283                {
     1284                    if (Sockets[i].PosValides)
     1285                    {
     1286                        Sockets[i].AttenteExecution=0;
     1287                        Sockets[i].etape++;
     1288                    }
     1289                    else
     1290                    {
     1291                        // on réitÚre l'ordre précédent si rien ne se passe
     1292
     1293                        Sockets[i].AttenteExecution++;
     1294
     1295                        if (Sockets[i].AttenteExecution>MAXATTENTE)
     1296                        {
     1297                            Sockets[i].etape=2;
     1298                            Sockets[i].AttenteExecution=0;
     1299                            Sockets[i].AnomaliesExecution++;
     1300                        }
     1301
     1302                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
     1303                        {
     1304                            Sockets[i].etape=3;
     1305
     1306                            // if ( compt % 1000 == 0)
     1307                            {
     1308                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : la position retournee n est pas valide. \
     1309                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
     1310                                Sockets[i].Connected=false;
     1311                            }
     1312                        }
     1313                    }
     1314                }
     1315                break;
     1316
     1317                //ack goto  ?
     1318                case 4 :
     1319                {
     1320                    if (Sockets[i].ack_goto)
     1321                    {
     1322                        Sockets[i].AttenteExecution=0;
     1323                        Sockets[i].AnomaliesExecution=0;
     1324                        Sockets[i].etape++;
     1325                    }
     1326                    else
     1327                    {
     1328                        // on réitÚre l'ordre précédent si rien ne se passe
     1329
     1330                        Sockets[i].AttenteExecution++;
     1331
     1332                        if (Sockets[i].AttenteExecution>MAXATTENTE)
     1333                        {
     1334                            Sockets[i].etape=4;
     1335                            Sockets[i].AttenteExecution=0;
     1336                            Sockets[i].AnomaliesExecution++;
     1337                        }
     1338
     1339                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
     1340                        {
     1341                            Sockets[i].etape=6;
     1342
     1343                            // if ( compt % 1000 == 0)
     1344                            {
     1345                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre GOTO. \
     1346                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
     1347                                Sockets[i].Connected=false;
     1348                            }
     1349                        }
     1350                    }
     1351                }
     1352                break;
     1353
     1354                //goto ok  ?
     1355                case 5 :
     1356                {
     1357                    if (Sockets[i].GotoOk)
     1358                    {
     1359                        Sockets[i].AttenteExecution=0;
     1360                        Sockets[i].AnomaliesExecution=0;
     1361                        Sockets[i].etape++;
     1362                    }
     1363                    else
     1364                    {
     1365                        // on réitÚre l'ordre précédent si rien ne se passe
     1366
     1367                        Sockets[i].AttenteExecution++;
     1368
     1369                        if (Sockets[i].AttenteExecution>MAXATTENTE)
     1370                        {
     1371                            Sockets[i].etape=5;
     1372                            Sockets[i].AttenteExecution=0;
     1373                            Sockets[i].AnomaliesExecution++;
     1374                        }
     1375
     1376                        if (Sockets[i].AnomaliesExecution>MAXANOMALIESGOTO)
     1377                        {
     1378                            Sockets[i].etape=6;
     1379
     1380                            // if ( compt % 1000 == 0)
     1381                            {
     1382                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : l antenne n a pas renvoye GOTO/OK. \
     1383                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
     1384                                Sockets[i].Connected=false;
     1385
     1386
     1387                            }
     1388                        }
     1389                    }
     1390                }
     1391                break;
     1392
     1393                }
     1394            }
     1395        }
     1396
     1397
     1398
     1399
     1400
     1401
     1402        // Détection d'anomalies concernant l'envoi de trames sur la socket. déconnexion du micro-cont ?
     1403
     1404        for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
     1405            {
     1406                if (Sockets[i].sendalertes > 0)
     1407                {
     1408                    Sockets[i].etape=5;
     1409
     1410                    //  if ( compt % 1000 == 0)
     1411                    {
     1412                        IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : deconnexion de l antenne.", Sockets[i].IP.c_str());
     1413
     1414                        Sockets[i].Connected=false;
     1415                    }
     1416                }
     1417            }
     1418
     1419
     1420
     1421        //On attend que toutes les antennes soient prêtes pour lancer l'ordre Goto -> meilleure synchronisation
     1422
     1423        int num=0;
     1424
     1425        for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
     1426            {
     1427                if (Sockets[i].etape == 3) num++; //fin de la procédure LecturePosition. Les antennes sont prêtes
     1428                //à recevoir l'ordre GOto
     1429            }
     1430
     1431        if ((num == AntennesConnectees()) && (num>0))
     1432        {
     1433            for (int i=1; i<SocketsNumber; i++ ) if (Sockets[i].Connected)
     1434                {
     1435                    Sockets[i].ack_goto=false;
     1436                    Sockets[i].AttenteExecution=0;
     1437                    Sockets[i].AnomaliesExecution=0;
     1438
     1439                    if (!GOTO(i, Sockets[i].Pos.x - TargetPosition.x, Sockets[i].Pos.y - TargetPosition.y )) Sockets[i].sendalertes++;
     1440
     1441                    Sockets[i].etape++;
     1442                }
     1443        }
     1444    }
     1445
    14501446    ISPOLLRunning=false;
    1451   }
    1452  
    1453  
    1454  
    1455   /**************************************************************************************
    1456   **
    1457   ***************************************************************************************/
    1458   bool BAO::process_coords()
    1459   {
     1447}
     1448
     1449
     1450
     1451/**************************************************************************************
     1452**
     1453***************************************************************************************/
     1454bool BAO::process_coords()
     1455{
    14601456    switch (currentSet)
    14611457    {
    1462       // Transit
    1463       case BAO_TRANSIT:
    1464        
    1465         EquatorialCoordsWNP.s = IPS_BUSY;
    1466        
    1467         IDSetNumber (&EquatorialCoordsWNP, NULL);
    1468        
    1469         InitAntennes();
    1470        
    1471         JJAnc=JJ;
    1472        
    1473         TrackingMode = 1;
    1474        
    1475         Goto=true;
    1476        
    1477         LastGotoOK=false;
    1478        
    1479         LecturePosition=true;
    1480        
    1481         ADDEC2Motor(targetRA, targetDEC);
    1482        
    1483         break;
    1484        
    1485         // Tracking
    1486       case BAO_TRACKING:
    1487        
    1488         EquatorialCoordsWNP.s = IPS_BUSY;
    1489        
    1490         IDSetNumber (&EquatorialCoordsWNP, NULL);
    1491        
    1492         InitAntennes();
    1493        
    1494         JJAnc=JJ;
    1495        
    1496         TrackingMode = 2;
    1497        
    1498         Goto=true;
    1499        
    1500         LastGotoOK=false;
    1501        
    1502         LecturePosition=true;
    1503        
    1504         ADDEC2Motor(targetRA, targetDEC);
    1505        
    1506         break;
    1507     }
    1508    
     1458        // Transit
     1459    case BAO_TRANSIT:
     1460
     1461        EquatorialCoordsWNP.s = IPS_BUSY;
     1462
     1463        IDSetNumber (&EquatorialCoordsWNP, NULL);
     1464
     1465        InitAntennes();
     1466
     1467        JJAnc=JJ;
     1468
     1469        TrackingMode = 1;
     1470
     1471        Goto=true;
     1472
     1473        LastGotoOK=false;
     1474
     1475        LecturePosition=true;
     1476
     1477        ADDEC2Motor(targetRA, targetDEC);
     1478
     1479        break;
     1480
     1481        // Tracking
     1482    case BAO_TRACKING:
     1483
     1484        EquatorialCoordsWNP.s = IPS_BUSY;
     1485
     1486        IDSetNumber (&EquatorialCoordsWNP, NULL);
     1487
     1488        InitAntennes();
     1489
     1490        JJAnc=JJ;
     1491
     1492        TrackingMode = 2;
     1493
     1494        Goto=true;
     1495
     1496        LastGotoOK=false;
     1497
     1498        LecturePosition=true;
     1499
     1500        ADDEC2Motor(targetRA, targetDEC);
     1501
     1502        break;
     1503    }
     1504
    15091505    return true;
    1510   }
    1511  
    1512   /**************************************************************************************
    1513   **
    1514   ***************************************************************************************/
    1515   int BAO::get_switch_index(ISwitchVectorProperty *sp)
    1516   {
     1506}
     1507
     1508/**************************************************************************************
     1509**
     1510***************************************************************************************/
     1511int BAO::get_switch_index(ISwitchVectorProperty *sp)
     1512{
    15171513    for (int i=0; i < sp->nsp ; i++)
    1518       if (sp->sp[i].s == ISS_ON)
    1519         return i;
    1520      
    1521       return -1;
    1522   }
    1523  
    1524   /**************************************************************************************
    1525   ** Activation de l'interface
    1526   ***************************************************************************************/
    1527   void BAO::connect_telescope()
    1528   {
     1514        if (sp->sp[i].s == ISS_ON)
     1515            return i;
     1516
     1517    return -1;
     1518}
     1519
     1520/**************************************************************************************
     1521** Activation de l'interface
     1522***************************************************************************************/
     1523void BAO::connect_telescope()
     1524{
    15291525    switch (ConnectSP.sp[0].s)
    15301526    {
    1531       case ISS_ON:
    1532         ConnectS[0].s = ISS_ON;
    1533         ConnectS[1].s = ISS_OFF;
    1534         IDLog("\nHello BAORadio !\n");
    1535        
    1536         ConnectSP.s = IPS_OK;
    1537         IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
    1538        
    1539        
    1540         break;
    1541        
    1542       case ISS_OFF:
    1543         ConnectS[0].s = ISS_OFF;
    1544         ConnectS[1].s = ISS_ON;
    1545         ConnectSP.s = IPS_IDLE;
    1546        
    1547         SocketsNumber=1;
    1548         InitThreadOK=false;
    1549        
    1550         for (int i=0; i<MAXHOSTNAME; i++)
    1551         {
    1552           Sockets[i].Connected=false;
    1553           Sockets[i].IP="";
    1554           Sockets[i].new_sock.shutdown();
    1555         }
    1556        
    1557         InitAntennes();
    1558        
    1559         IDSetSwitch (&ConnectSP, "BAORadio is offline.");
    1560         IDLog("Telescope is offline.");
    1561        
    1562         break;
    1563     }
    1564   }
    1565  
    1566   /**************************************************************************************
    1567   **
    1568   ***************************************************************************************/
    1569   void BAO::get_initial_data()
    1570   {
     1527    case ISS_ON:
     1528        ConnectS[0].s = ISS_ON;
     1529        ConnectS[1].s = ISS_OFF;
     1530        IDLog("\nHello BAORadio !\n");
     1531
     1532        ConnectSP.s = IPS_OK;
     1533        IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
     1534
     1535
     1536        break;
     1537
     1538    case ISS_OFF:
     1539        ConnectS[0].s = ISS_OFF;
     1540        ConnectS[1].s = ISS_ON;
     1541        ConnectSP.s = IPS_IDLE;
     1542
     1543        SocketsNumber=1;
     1544        InitThreadOK=false;
     1545
     1546        for (int i=0; i<MAXHOSTNAME; i++)
     1547        {
     1548            Sockets[i].Connected=false;
     1549            Sockets[i].IP="";
     1550            Sockets[i].new_sock.shutdown();
     1551        }
     1552
     1553        InitAntennes();
     1554
     1555        IDSetSwitch (&ConnectSP, "BAORadio is offline.");
     1556        IDLog("Telescope is offline.");
     1557
     1558        break;
     1559    }
     1560}
     1561
     1562/**************************************************************************************
     1563**
     1564***************************************************************************************/
     1565void BAO::get_initial_data()
     1566{
    15711567    //  IDSetNumber (&EquatorialCoordsRNP, NULL);
    1572    
    1573      
    1574   }
    1575  
    1576   /**************************************************************************************
    1577   **
    1578   ***************************************************************************************/
    1579   void BAO::slew_error(int slewCode)
    1580   {
     1568
     1569
     1570}
     1571
     1572/**************************************************************************************
     1573**
     1574***************************************************************************************/
     1575void BAO::slew_error(int slewCode)
     1576{
    15811577    OnCoordSetSP.s = IPS_IDLE;
    1582    
     1578
    15831579    if (slewCode == 1)
    1584       IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
     1580        IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
    15851581    else if (slewCode == 2)
    1586       IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
     1582        IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
    15871583    else
    1588       IDSetSwitch (&OnCoordSetSP, "Slew failed.");
    1589   }
    1590  
    1591   /**************************************************************************************
    1592   **
    1593   ***************************************************************************************/
    1594   void BAO::enable_simulation(bool enable)
    1595   {
     1584        IDSetSwitch (&OnCoordSetSP, "Slew failed.");
     1585}
     1586
     1587/**************************************************************************************
     1588**
     1589***************************************************************************************/
     1590void BAO::enable_simulation(bool enable)
     1591{
    15961592    simulation = enable;
    1597    
     1593
    15981594    if (simulation)
    1599       IDLog("Warning: Simulation is activated.\n");
     1595        IDLog("Warning: Simulation is activated.\n");
    16001596    else
    1601       IDLog("Simulation is disabled.\n");
    1602   }
    1603  
    1604   /**************************************************************************************
    1605   **
    1606   ***************************************************************************************/
    1607   void BAO::connection_lost()
    1608   {
     1597        IDLog("Simulation is disabled.\n");
     1598}
     1599
     1600/**************************************************************************************
     1601**
     1602***************************************************************************************/
     1603void BAO::connection_lost()
     1604{
    16091605    ConnectSP.s = IPS_IDLE;
    16101606    IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
    16111607    return;
    1612   }
    1613  
    1614   /**************************************************************************************
    1615   **
    1616   ***************************************************************************************/
    1617   void BAO::connection_resumed()
    1618   {
     1608}
     1609
     1610/**************************************************************************************
     1611**
     1612***************************************************************************************/
     1613void BAO::connection_resumed()
     1614{
    16191615    ConnectS[0].s = ISS_ON;
    16201616    ConnectS[1].s = ISS_OFF;
    16211617    ConnectSP.s = IPS_OK;
    1622    
     1618
    16231619    IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
    1624   }
    1625  
    1626  
    1627   /**************************************************************************************
    1628   **  Envoi d'une commande sur le socket puis attente de l'acknowledge
    1629   ***************************************************************************************/
    1630  
    1631   bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
    1632   {
     1620}
     1621
     1622
     1623/**************************************************************************************
     1624**  Envoi d'une commande sur le socket puis attente de l'acknowledge
     1625***************************************************************************************/
     1626
     1627bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
     1628{
    16331629    char chaine[MAXCARACTERES];
    1634    
     1630
    16351631    try
    16361632    {
    1637       sprintf(chaine, "%s%s\n", Commande, Params);
    1638      
    1639       Sockets[numsocket].new_sock << chaine;
     1633        sprintf(chaine, "%s%s\n", Commande, Params);
     1634
     1635        Sockets[numsocket].new_sock << chaine;
    16401636    }
    16411637    catch (SocketException& e)
    1642     {       
    1643       Sockets[numsocket].new_sock.shutdown();
    1644       Sockets[numsocket].new_sock.create();
    1645       Sockets[numsocket].Connected = Sockets[numsocket].new_sock.connect((std::string)Sockets[numsocket].IP);
    1646      
    1647       if (Sockets[numsocket].Connected)
    1648       {
    1649         Sockets[numsocket].AttenteExecution=0;
    1650         Sockets[numsocket].AnomaliesExecution=0;
    1651       }
    1652      
    1653       //  if (AntennesConnectees() == 0) { InitAntennes(); InitThreadOK=false;}
    1654      
    1655       std::string oss;
    1656       oss="COMMANDE exception : " + e.description() + "\n";
    1657       size_t size = oss.size() + 1;
    1658       char* buffer = new char[size];
    1659       strncpy(buffer, oss.c_str(), size);
    1660      
    1661       IDLog(buffer);
    1662      
    1663       delete [] buffer;
    1664      
    1665       return false;
    1666     }
    1667    
     1638    {
     1639        Sockets[numsocket].new_sock.shutdown();
     1640        Sockets[numsocket].new_sock.create();
     1641        Sockets[numsocket].Connected = Sockets[numsocket].new_sock.connect((std::string)Sockets[numsocket].IP);
     1642
     1643        if (Sockets[numsocket].Connected)
     1644        {
     1645            Sockets[numsocket].AttenteExecution=0;
     1646            Sockets[numsocket].AnomaliesExecution=0;
     1647        }
     1648
     1649        //  if (AntennesConnectees() == 0) { InitAntennes(); InitThreadOK=false;}
     1650
     1651        std::string oss;
     1652        oss="COMMANDE exception : " + e.description() + "\n";
     1653        size_t size = oss.size() + 1;
     1654        char* buffer = new char[size];
     1655        strncpy(buffer, oss.c_str(), size);
     1656
     1657        IDLog(buffer);
     1658
     1659        delete [] buffer;
     1660
     1661        return false;
     1662    }
     1663
    16681664    return true;
    1669   }
    1670  
    1671  
    1672   /**************************************************************************************
    1673   ** Commande POSITION
    1674   ***************************************************************************************/
    1675  
    1676   bool BAO::POSITION(int numsocket)
    1677   {
     1665}
     1666
     1667
     1668/**************************************************************************************
     1669** Commande POSITION
     1670***************************************************************************************/
     1671
     1672bool BAO::POSITION(int numsocket)
     1673{
    16781674    return COMMANDE(numsocket, (char*)"P", (char*)"");
    1679   }
    1680  
    1681   /**************************************************************************************
    1682   ** Commande PARK
    1683   ***************************************************************************************/
    1684  
    1685   bool BAO::PARK(int numsocket)
    1686   {
     1675}
     1676
     1677/**************************************************************************************
     1678** Commande PARK
     1679***************************************************************************************/
     1680
     1681bool BAO::PARK(int numsocket)
     1682{
    16871683    return COMMANDE(numsocket, (char*)"Z", (char*)"");
    1688   }
    1689  
    1690   /**************************************************************************************
    1691   ** Commande ABORT
    1692   ***************************************************************************************/
    1693  
    1694   bool BAO::ABORT(int numsocket)
    1695   {
     1684}
     1685
     1686/**************************************************************************************
     1687** Commande ABORT
     1688***************************************************************************************/
     1689
     1690bool BAO::ABORT(int numsocket)
     1691{
    16961692    return COMMANDE(numsocket, (char*)"A", (char*)"");
    1697   }
    1698  
    1699  
    1700   /**************************************************************************************
    1701   ** Commande GOTO
    1702   ***************************************************************************************/
    1703  
    1704   bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
    1705   {
     1693}
     1694
     1695
     1696/**************************************************************************************
     1697** Commande GOTO
     1698***************************************************************************************/
     1699
     1700bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
     1701{
    17061702    char Params[MAXCARACTERES];
    17071703    char sensAz;
    17081704    char sensAlt;
    1709    
     1705
    17101706    sensAlt='b';
    17111707    sensAz='b';
    1712    
     1708
    17131709    if (deltaAz<0)
    17141710    {
    1715       deltaAz=-deltaAz;
    1716       sensAz='f';
    1717     }
    1718    
     1711        deltaAz=-deltaAz;
     1712        sensAz='f';
     1713    }
     1714
    17191715    if (deltaAlt<0)
    17201716    {
    1721       deltaAlt=-deltaAlt;
    1722       sensAlt='f';
    1723     }
    1724    
     1717        deltaAlt=-deltaAlt;
     1718        sensAlt='f';
     1719    }
     1720
    17251721    sprintf(Params, "%c%04i%c%04i", sensAz, deltaAz, sensAlt, deltaAlt);
    1726    
     1722
    17271723    return COMMANDE(numsocket, (char*)"G", Params);
    1728   }
    1729  
    1730  
    1731  
     1724}
     1725
     1726
     1727
  • BAORadio/libindi/libindi/drivers/telescope/lx200basic.cpp

    r490 r501  
    163163   IDLog("Driver Version: 2007-09-28\n");
    164164 
    165    //enableSimulation(true); 
    166 }
     165   enable_simulation(false); 
     166
     167 }
    167168
    168169/**************************************************************************************
     
    342343           #endif
    343344           
    344            if ( (error_code = setObjectRA(fd, newRA)) < 0 || ( error_code = setObjectDEC(fd, newDEC)) < 0)
     345           if (!simulation && ( (error_code = setObjectRA(fd, newRA)) < 0 || ( error_code = setObjectDEC(fd, newDEC)) < 0))
    345346           {
    346347             handle_error(&EquatorialCoordsWNP, error_code, "Setting RA/DEC");
     
    574575void LX200Basic::ISPoll()
    575576{       
    576         if (is_connected() == false)
     577        if (is_connected() == false || simulation)
    577578         return;
    578579
     
    684685          }
    685686
    686           if ((error_code = Slew(fd)))
     687          if ( !simulation && (error_code = Slew(fd)))
    687688          {
    688689            slew_error(error_code);
     
    716717          if (dx >= (TrackAccuracyN[0].value/(60.0*15.0)) || (dy >= TrackAccuracyN[1].value/60.0))
    717718          {
    718                 if ((error_code = Slew(fd)))
     719                if ( !simulation && (error_code = Slew(fd)))
    719720                {
    720721                        slew_error(error_code);
     
    751752          EquatorialCoordsWNP.s = IPS_IDLE;
    752753           
    753           if ( ( error_code = Sync(fd, syncString) < 0) )
     754          if ( !simulation && ( error_code = Sync(fd, syncString) < 0) )
    754755          {
    755756                IDSetNumber( &EquatorialCoordsWNP , "Synchronization failed.");
    756757                return false;
     758          }
     759
     760          if (simulation)
     761          {
     762             EquatorialCoordsRN[0].value = EquatorialCoordsWN[0].value;
     763             EquatorialCoordsRN[1].value = EquatorialCoordsWN[1].value;
    757764          }
    758765
  • BAORadio/libindi/libindi/drivers/telescope/lx200generic.cpp

    r490 r501  
    165165 Property: Movement (Arrow keys on handset). West/East
    166166*********************************************/
     167
    167168static ISwitch MovementWES[]       = {{"MOTION_WEST", "West", ISS_OFF, 0, 0}, {"MOTION_EAST", "East", ISS_OFF, 0, 0}};
    168169ISwitchVectorProperty MovementWESP      = { mydev, "TELESCOPE_MOTION_WE", "West/East", MOTION_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, MovementWES, NARRAY(MovementWES), "", 0};
     
    314315  strcpy(TimeTP.device , newName );
    315316  strcpy(UTCOffsetNP.device , newName );
     317
    316318  strcpy(SDTimeNP.device , newName );
    317319
     
    338340{
    339341  static int isInit=0;
     342  char *envDev = getenv("INDIDEV");
    340343
    341344 if (isInit)
     
    355358  {
    356359     fprintf(stderr , "initilizaing from LX200 classic device...\n");
    357      // 1. mydev = device_name
    358      changeAllDeviceNames("LX200 Classic");
    359      // 2. device = sub_class
     360
    360361     telescope = new LX200Classic();
    361      telescope->setCurrentDeviceName("LX200 Classic");
     362     if (envDev != NULL)
     363     {
     364         changeAllDeviceNames(envDev);
     365         telescope->setCurrentDeviceName(envDev);
     366     }
     367     else
     368     {
     369        // 1. mydev = device_name
     370        changeAllDeviceNames("LX200 Classic");
     371        telescope->setCurrentDeviceName("LX200 Classic");
     372     }
    362373
    363374     MaxReticleFlashRate = 3;
     
    367378  {
    368379     fprintf(stderr , "initilizaing from LX200 GPS device...\n");
    369      // 1. mydev = device_name
    370      changeAllDeviceNames("LX200 GPS");
     380
    371381     // 2. device = sub_class
    372382     telescope = new LX200GPS();
    373      telescope->setCurrentDeviceName("LX200 GPS");
     383
     384     if (envDev != NULL)
     385     {
     386         // 1. mydev = device_name
     387         changeAllDeviceNames(envDev);
     388         telescope->setCurrentDeviceName(envDev);
     389     }
     390     else
     391     {
     392         // 1. mydev = device_name
     393         changeAllDeviceNames("LX200 GPS");
     394         telescope->setCurrentDeviceName("LX200 GPS");
     395     }
     396
     397
    374398
    375399     MaxReticleFlashRate = 9;
     
    379403
    380404    IDLog("Initilizaing from LX200 16 device...\n");
    381     // 1. mydev = device_name
    382     changeAllDeviceNames("LX200 16");
     405
    383406    // 2. device = sub_class
    384407   telescope = new LX200_16();
    385    telescope->setCurrentDeviceName("LX200 16");
     408
     409   if (envDev != NULL)
     410   {
     411       // 1. mydev = device_name
     412       changeAllDeviceNames(envDev);
     413       telescope->setCurrentDeviceName(envDev);
     414   }
     415   else
     416   {
     417       changeAllDeviceNames("LX200 16");
     418       telescope->setCurrentDeviceName("LX200 16");
     419   }
    386420
    387421   MaxReticleFlashRate = 3;
     
    391425   fprintf(stderr , "initilizaing from autostar device...\n");
    392426 
    393    // 1. change device name
    394    changeAllDeviceNames("LX200 Autostar");
    395427   // 2. device = sub_class
    396428   telescope = new LX200Autostar();
    397    telescope->setCurrentDeviceName("LX200 Autostar");
     429
     430   if (envDev != NULL)
     431   {
     432       // 1. change device name
     433       changeAllDeviceNames(envDev);
     434       telescope->setCurrentDeviceName(envDev);
     435   }
     436   else
     437   {
     438       // 1. change device name
     439       changeAllDeviceNames("LX200 Autostar");
     440       telescope->setCurrentDeviceName("LX200 Autostar");
     441   }
    398442
    399443   MaxReticleFlashRate = 9;
     
    403447   fprintf(stderr , "initilizaing from ap device...\n");
    404448 
    405    // 1. change device name
    406    changeAllDeviceNames("LX200 Astro-Physics");
     449
    407450   // 2. device = sub_class
    408451   telescope = new LX200AstroPhysics();
    409    telescope->setCurrentDeviceName("LX200 Astro-Physics");
     452
     453   if (envDev != NULL)
     454   {
     455       // 1. change device name
     456       changeAllDeviceNames(envDev);
     457       telescope->setCurrentDeviceName(envDev);
     458   }
     459   else
     460   {
     461       // 1. change device name
     462       changeAllDeviceNames("LX200 Astro-Physics");
     463        telescope->setCurrentDeviceName("LX200 Astro-Physics");
     464    }
     465
    410466
    411467   MaxReticleFlashRate = 9;
     
    415471 {
    416472  telescope = new LX200Generic();
    417   telescope->setCurrentDeviceName("LX200 Generic");
     473
     474  if (envDev != NULL)
     475  {
     476      // 1. change device name
     477      changeAllDeviceNames(envDev);
     478      telescope->setCurrentDeviceName(envDev);
     479  }
     480  else
     481  {
     482      // 1. change device name
     483      changeAllDeviceNames("LX200 Generic");
     484      telescope->setCurrentDeviceName("LX200 Generic");
     485  }
     486
    418487 }
    419488
  • BAORadio/libindi/libindi/examples/tutorial_two.c

    r490 r501  
    100100
    101101/* Equatorial EOD Coord Request. This property is for requesting changes to target equatorial coordinates. However, the CURRENT coordinates are reported in EQUATORIAL_EOD_COORDS above.*/
    102 static INumber eqNR[] = {{"RA_REQUEST" ,"RA  H:M:S" , "%10.6m" ,0. , 24., 0., 0., 0, 0, 0},
    103                          {"DEC_REQUEST", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0}};
     102static INumber eqNR[] = {{"RA" ,"RA  H:M:S" , "%10.6m" ,0. , 24., 0., 0., 0, 0, 0},
     103                         {"DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0}};
    104104static INumberVectorProperty eqNPR = {  mydev, "EQUATORIAL_EOD_COORD_REQUEST", "Equatorial Request",  MAIN_GROUP , IP_RW, 0, IPS_IDLE,  eqNR, NARRAY(eqNR), "", 0};
    105105
  • BAORadio/libindi/libindi/indiapi.h

    r490 r501  
    4848<li><a href="indicom_8h.html">INDI Common Routine Library</a></li>
    4949<li><a href="lilxml_8h.html">INDI LilXML Library</a></li>
    50 <li><a href="http://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/cfitsio.html">CFITSIO Library</a></li>
     50<li><a href="group__configFunctions.html">Configuration</a></li>
     51<li><a href="classINDI_1_1BaseClient.html">Client API</a></li>
    5152</ul>
    5253
     
    7475
    7576/* INDI Library version */
    76 #define INDI_LIBV       0.6
     77#define INDI_LIBV       0.7
    7778
    7879/*******************************************************************************
  • BAORadio/libindi/libindi/indidevapi.h

    r490 r501  
    302302    \param snooped_property name of the snooped property in the device.
    303303*/
    304 extern void IDSnoopDevice (const char *snooped_device, char *snooped_property);
     304extern void IDSnoopDevice (const char *snooped_device, const char *snooped_property);
    305305
    306306/** \brief Function a Driver calls to control whether they will receive BLOBs from snooped devices.
    307     \param snooped_device_name name of the device to snoop.
     307    \param snooped_device name of the device to snoop.
    308308    \param bh How drivers handle BLOBs incoming from snooping drivers.
    309309*/
     
    403403/** \brief Find an IText member in a vector text property.
    404404*
    405 * \param tp a pointer to a text vector property.
     405* \param tvp a pointer to a text vector property.
    406406* \param name the name of the member to search for.
    407407* \return a pointer to an IText member on match, or NULL if nothing is found.
    408408*/
    409 extern IText   *IUFindText  (const ITextVectorProperty *tp, const char *name);
     409extern IText   *IUFindText  (const ITextVectorProperty *tvp, const char *name);
    410410
    411411/** \brief Find an INumber member in a number text property.
    412412*
    413 * \param tp a pointer to a number vector property.
     413* \param nvp a pointer to a number vector property.
    414414* \param name the name of the member to search for.
    415415* \return a pointer to an INumber member on match, or NULL if nothing is found.
    416416*/
    417 extern INumber *IUFindNumber(const INumberVectorProperty *tp, const char *name);
     417extern INumber *IUFindNumber(const INumberVectorProperty *nvp, const char *name);
    418418
    419419/** \brief Find an ISwitch member in a vector switch property.
    420420*
    421 * \param tp a pointer to a switch vector property.
     421* \param svp a pointer to a switch vector property.
    422422* \param name the name of the member to search for.
    423423* \return a pointer to an ISwitch member on match, or NULL if nothing is found.
    424424*/
    425 extern ISwitch *IUFindSwitch(const ISwitchVectorProperty *tp, const char *name);
     425extern ISwitch *IUFindSwitch(const ISwitchVectorProperty *svp, const char *name);
     426
     427/** \brief Find an ILight member in a vector Light property.
     428*
     429* \param lvp a pointer to a Light vector property.
     430* \param name the name of the member to search for.
     431* \return a pointer to an ILight member on match, or NULL if nothing is found.
     432*/
     433extern ILight *IUFindLight(const ILightVectorProperty *lvp, const char *name);
     434
     435/** \brief Find an IBLOB member in a vector BLOB property.
     436*
     437* \param bvp a pointer to a BLOB vector property.
     438* \param name the name of the member to search for.
     439* \return a pointer to an IBLOB member on match, or NULL if nothing is found.
     440*/
     441extern IBLOB *IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name);
    426442
    427443/** \brief Returns the first ON switch it finds in the vector switch property.
     
    429445*   \note This is only valid for ISR_1OFMANY mode. That is, when only one switch out of many is allowed to be ON. Do not use this function if you can have multiple ON switches in the same vector property.
    430446*       
    431 * \param tp a pointer to a switch vector property.
     447* \param sp a pointer to a switch vector property.
    432448* \return a pointer to the \e first ON ISwitch member if found. If all switches are off, NULL is returned.
    433449*/
    434 extern ISwitch *IUFindOnSwitch (const ISwitchVectorProperty *tp);
     450extern ISwitch *IUFindOnSwitch (const ISwitchVectorProperty *sp);
    435451
    436452/** \brief Reset all switches in a switch vector property to OFF.
     
    517533extern void IUFillText(IText *tp, const char *name, const char * label, const char *initialText);
    518534
     535/** \brief Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
     536    \param bp pointer a BLOB property to fill
     537    \param name the BLOB name
     538    \param label the BLOB label
     539    \param format the BLOB format.
     540*/
     541extern void IUFillBLOB(IBLOB *bp, const char *name, const char * label, const char *format);
    519542
    520543/** \brief Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
     
    573596extern void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s);
    574597
     598/** \brief Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
     599    \param bvp pointer a BLOB vector property to fill
     600    \param bp pointer to an array of BLOBs
     601    \param nbp the dimension of bp
     602    \param dev the device name this vector property belongs to
     603    \param name the vector property name
     604    \param label the vector property label
     605    \param group the vector property group
     606    \param p the vector property permission
     607    \param timeout vector property timeout in seconds
     608    \param s the vector property initial state.
     609*/
     610extern void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s);
     611
     612
    575613/** \brief Update a snooped number vector property from the given XML root element.
    576614    \param root XML root elememnt containing the snopped property content
     
    706744#define INDI_UNUSED(x) (void) x
    707745
     746/** \brief Extract dev and name attributes from an XML element.
     747    \param root The XML element to be parsed.
     748    \param dev pointer to an allocated buffer to save the extracted element device name attribute.
     749           The buffer size must be at least MAXINDIDEVICE bytes.
     750    \param name pointer to an allocated buffer to save the extracted elemented name attribute.
     751           The buffer size must be at least MAXINDINAME bytes.
     752    \param msg pointer to an allocated char buffer to store error messages. The minimum buffer size is MAXRBUF.
     753    \return 0 if successful, -1 if error is encountered and msg is set.
     754*/
     755extern int crackDN (XMLEle *root, char **dev, char **name, char msg[]);
     756
     757/** \brief Extract property state (Idle, OK, Busy, Alert) from the supplied string.
     758    \param str A string representation of the state.
     759    \param ip Pointer to IPState structure to store the extracted property state.
     760    \return 0 if successful, -1 if error is encountered.
     761*/
     762extern int crackIPState (const char *str, IPState *ip);
     763
     764/** \brief Extract switch state (On or Off) from the supplied string.
     765    \param str A string representation of the switch state.
     766    \param ip Pointer to ISState structure to store the extracted switch state.
     767    \return 0 if successful, -1 if error is encountered.
     768*/
     769extern int crackISState (const char *str, ISState *ip);
     770
     771/** \brief Extract property permission state (RW, RO, WO) from the supplied string.
     772    \param str A string representation of the permission state.
     773    \param ip Pointer to IPerm structure to store the extracted permission state.
     774    \return 0 if successful, -1 if error is encountered.
     775*/
     776extern int crackIPerm (const char *str, IPerm *ip);
     777
     778/** \brief Extract switch rule (OneOfMany, OnlyOne..etc) from the supplied string.
     779    \param str A string representation of the switch rule.
     780    \param ip Pointer to ISRule structure to store the extracted switch rule.
     781    \return 0 if successful, -1 if error is encountered.
     782*/
     783extern int crackISRule (const char *str, ISRule *ip);
     784
     785/** \return Returns a string representation of the supplied property state. */
     786extern const char *pstateStr(IPState s);
     787/** \return Returns a string representation of the supplied switch status. */
     788extern const char *sstateStr(ISState s);
     789/** \return Returns a string representation of the supplied switch rule. */
     790extern const char *ruleStr(ISRule r);
     791/** \return Returns a string representation of the supplied permission value. */
     792extern const char *permStr(IPerm p);
     793
     794extern void xmlv1(void);
     795
    708796#ifdef __cplusplus
    709797}
  • BAORadio/libindi/libindi/indidrivermain.c

    r490 r501  
    33    Copyright (C) 2003-2006 Elwood C. Downey
    44
    5                         Modified by Jasem Mutlaq (2003-2006)
     5                        Updated by Jasem Mutlaq (2003-2010)
    66
    77    This library is free software; you can redistribute it and/or
     
    4646#include "indidevapi.h"
    4747#include "indicom.h"
     48#include "indidriver.h"
    4849
    49 static void usage(void);
    50 static void clientMsgCB(int fd, void *arg);
    51 static int dispatch (XMLEle *root, char msg[]);
    52 static int crackDN (XMLEle *root, char **dev, char **name, char msg[]);
    53 static int isPropDefined(const char *property_name);
    54 static int crackIPState (const char *str, IPState *ip);
    55 static int crackISState (const char *str, ISState *ip);
    56 static void xmlv1(void);
    57 const char *pstateStr(IPState s);
    58 const char *sstateStr(ISState s);
    59 const char *ruleStr(ISRule r);
    60 const char *permStr(IPerm p);
     50#define MAXRBUF 2048
    6151
     52ROSC *roCheck;
     53int nroCheck;                   /* # of elements in roCheck */
    6254
    63 static int nroCheck;                    /* # of elements in roCheck */
    64 static int verbose;                     /* chatty */
     55int verbose;                    /* chatty */
    6556char *me;                               /* a.out name */
    66 static LilXML *clixml;                  /* XML parser context */
     57LilXML *clixml;                 /* XML parser context */
    6758
    68 /* insure RO properties are never modified. RO Sanity Check */
    69 typedef struct
    70 {
    71   char propName[MAXINDINAME];
    72   IPerm perm;
    73 } ROSC;
    74 
    75 static ROSC *roCheck;
     59static void  usage(void);
    7660
    7761int
     
    10993        clixml =  newLilXML();
    11094        addCallback (0, clientMsgCB, NULL);
    111        
    112         nroCheck = 0;
    113         roCheck = NULL;
    11495
    11596        /* service client */
     
    121102}
    122103
    123 /* Return 1 is property is already cached, 0 otherwise */
    124 static int isPropDefined(const char *property_name)
     104/* print usage message and exit (1) */
     105static void  usage(void)
    125106{
    126   int i=0;
    127  
    128   for (i=0; i < nroCheck; i++)
    129     if (!strcmp(property_name, roCheck[i].propName))
    130         return 1;
     107            fprintf (stderr, "Usage: %s [options]\n", me);
     108            fprintf (stderr, "Purpose: INDI Device driver framework.\n");
     109            fprintf (stderr, "Options:\n");
     110            fprintf (stderr, " -v    : more verbose to stderr\n");
    131111
    132   return 0;
    133 
     112            exit (1);
    134113}
    135114
    136 /* functions we define that drivers may call */
    137 
    138 /* tell client to create a text vector property */
    139 void
    140 IDDefText (const ITextVectorProperty *tvp, const char *fmt, ...)
    141 {
    142         int i;
    143         ROSC *SC;
    144 
    145         xmlv1();
    146         printf ("<defTextVector\n");
    147         printf ("  device='%s'\n", tvp->device);
    148         printf ("  name='%s'\n", tvp->name);
    149         printf ("  label='%s'\n", tvp->label);
    150         printf ("  group='%s'\n", tvp->group);
    151         printf ("  state='%s'\n", pstateStr(tvp->s));
    152         printf ("  perm='%s'\n", permStr(tvp->p));
    153         printf ("  timeout='%g'\n", tvp->timeout);
    154         printf ("  timestamp='%s'\n", timestamp());
    155         if (fmt) {
    156             va_list ap;
    157             va_start (ap, fmt);
    158             printf ("  message='");
    159             vprintf (fmt, ap);
    160             printf ("'\n");
    161             va_end (ap);
    162         }
    163         printf (">\n");
    164 
    165         for (i = 0; i < tvp->ntp; i++) {
    166             IText *tp = &tvp->tp[i];
    167             printf ("  <defText\n");
    168             printf ("    name='%s'\n", tp->name);
    169             printf ("    label='%s'>\n", tp->label);
    170             printf ("      %s\n", tp->text ? tp->text : "");
    171             printf ("  </defText>\n");
    172         }
    173 
    174         printf ("</defTextVector>\n");
    175 
    176         if (!isPropDefined(tvp->name))
    177         {       
    178                 /* Add this property to insure proper sanity check */
    179                 roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
    180                                 : (ROSC *) malloc  ( sizeof(ROSC));
    181                 SC      = &roCheck[nroCheck++];
    182        
    183                 strcpy(SC->propName, tvp->name);
    184                 SC->perm = tvp->p;
    185         }
    186        
    187         fflush (stdout);
    188 }
    189 
    190 /* tell client to create a new numeric vector property */
    191 void
    192 IDDefNumber (const INumberVectorProperty *n, const char *fmt, ...)
    193 {
    194         int i;
    195         ROSC *SC;
    196 
    197         xmlv1();
    198         printf ("<defNumberVector\n");
    199         printf ("  device='%s'\n", n->device);
    200         printf ("  name='%s'\n", n->name);
    201         printf ("  label='%s'\n", n->label);
    202         printf ("  group='%s'\n", n->group);
    203         printf ("  state='%s'\n", pstateStr(n->s));
    204         printf ("  perm='%s'\n", permStr(n->p));
    205         printf ("  timeout='%g'\n", n->timeout);
    206         printf ("  timestamp='%s'\n", timestamp());
    207         if (fmt) {
    208             va_list ap;
    209             va_start (ap, fmt);
    210             printf ("  message='");
    211             vprintf (fmt, ap);
    212             printf ("'\n");
    213             va_end (ap);
    214         }
    215         printf (">\n");
    216 
    217         for (i = 0; i < n->nnp; i++) {
    218             INumber *np = &n->np[i];
    219             printf ("  <defNumber\n");
    220             printf ("    name='%s'\n", np->name);
    221             printf ("    label='%s'\n", np->label);
    222             printf ("    format='%s'\n", np->format);
    223             printf ("    min='%.20g'\n", np->min);
    224             printf ("    max='%.20g'\n", np->max);
    225             printf ("    step='%.20g'>\n", np->step);
    226             printf ("      %.20g\n", np->value);
    227             printf ("  </defNumber>\n");
    228         }
    229 
    230         printf ("</defNumberVector>\n");
    231        
    232         if (!isPropDefined(n->name))
    233         {       
    234                 /* Add this property to insure proper sanity check */
    235                 roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
    236                                 : (ROSC *) malloc  ( sizeof(ROSC));
    237                 SC      = &roCheck[nroCheck++];
    238        
    239                 strcpy(SC->propName, n->name);
    240                 SC->perm = n->p;
    241 
    242         }
    243        
    244         fflush (stdout);
    245 }
    246 
    247 /* tell client to create a new switch vector property */
    248 void
    249 IDDefSwitch (const ISwitchVectorProperty *s, const char *fmt, ...)
    250 
    251 {
    252         int i;
    253         ROSC *SC;
    254 
    255         xmlv1();
    256         printf ("<defSwitchVector\n");
    257         printf ("  device='%s'\n", s->device);
    258         printf ("  name='%s'\n", s->name);
    259         printf ("  label='%s'\n", s->label);
    260         printf ("  group='%s'\n", s->group);
    261         printf ("  state='%s'\n", pstateStr(s->s));
    262         printf ("  perm='%s'\n", permStr(s->p));
    263         printf ("  rule='%s'\n", ruleStr (s->r));
    264         printf ("  timeout='%g'\n", s->timeout);
    265         printf ("  timestamp='%s'\n", timestamp());
    266         if (fmt) {
    267             va_list ap;
    268             va_start (ap, fmt);
    269             printf ("  message='");
    270             vprintf (fmt, ap);
    271             printf ("'\n");
    272             va_end (ap);
    273         }
    274         printf (">\n");
    275 
    276         for (i = 0; i < s->nsp; i++) {
    277             ISwitch *sp = &s->sp[i];
    278             printf ("  <defSwitch\n");
    279             printf ("    name='%s'\n", sp->name);
    280             printf ("    label='%s'>\n", sp->label);
    281             printf ("      %s\n", sstateStr(sp->s));
    282             printf ("  </defSwitch>\n");
    283         }
    284 
    285         printf ("</defSwitchVector>\n");
    286        
    287         if (!isPropDefined(s->name))
    288         {       
    289                 /* Add this property to insure proper sanity check */
    290                 roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
    291                                 : (ROSC *) malloc  ( sizeof(ROSC));
    292                 SC      = &roCheck[nroCheck++];
    293        
    294                 strcpy(SC->propName, s->name);
    295                 SC->perm = s->p;
    296         }
    297        
    298         fflush (stdout);
    299 }
    300 
    301 /* tell client to create a new lights vector property */
    302 void
    303 IDDefLight (const ILightVectorProperty *lvp, const char *fmt, ...)
    304 {
    305         int i;
    306 
    307         xmlv1();
    308         printf ("<defLightVector\n");
    309         printf ("  device='%s'\n", lvp->device);
    310         printf ("  name='%s'\n", lvp->name);
    311         printf ("  label='%s'\n", lvp->label);
    312         printf ("  group='%s'\n", lvp->group);
    313         printf ("  state='%s'\n", pstateStr(lvp->s));
    314         printf ("  timestamp='%s'\n", timestamp());
    315         if (fmt) {
    316             va_list ap;
    317             va_start (ap, fmt);
    318             printf ("  message='");
    319             vprintf (fmt, ap);
    320             printf ("'\n");
    321             va_end (ap);
    322         }
    323         printf (">\n");
    324 
    325         for (i = 0; i < lvp->nlp; i++) {
    326             ILight *lp = &lvp->lp[i];
    327             printf ("  <defLight\n");
    328             printf ("    name='%s'\n", lp->name);
    329             printf ("    label='%s'>\n", lp->label);
    330             printf ("      %s\n", pstateStr(lp->s));
    331             printf ("  </defLight>\n");
    332         }
    333 
    334         printf ("</defLightVector>\n");
    335         fflush (stdout);
    336 }
    337 
    338 /* tell client to create a new BLOB vector property */
    339 void
    340 IDDefBLOB (const IBLOBVectorProperty *b, const char *fmt, ...)
    341 {
    342   int i;
    343   ROSC *SC;
    344 
    345         xmlv1();
    346         printf ("<defBLOBVector\n");
    347         printf ("  device='%s'\n", b->device);
    348         printf ("  name='%s'\n", b->name);
    349         printf ("  label='%s'\n", b->label);
    350         printf ("  group='%s'\n", b->group);
    351         printf ("  state='%s'\n", pstateStr(b->s));
    352         printf ("  perm='%s'\n", permStr(b->p));
    353         printf ("  timeout='%g'\n", b->timeout);
    354         printf ("  timestamp='%s'\n", timestamp());
    355         if (fmt) {
    356             va_list ap;
    357             va_start (ap, fmt);
    358             printf ("  message='");
    359             vprintf (fmt, ap);
    360             printf ("'\n");
    361             va_end (ap);
    362         }
    363         printf (">\n");
    364 
    365   for (i = 0; i < b->nbp; i++) {
    366     IBLOB *bp = &b->bp[i];
    367     printf ("  <defBLOB\n");
    368     printf ("    name='%s'\n", bp->name);
    369     printf ("    label='%s'\n", bp->label);
    370     printf ("  />\n");
    371   }
    372 
    373         printf ("</defBLOBVector>\n");
    374 
    375         if (!isPropDefined(b->name))
    376         {       
    377                 /* Add this property to insure proper sanity check */
    378                 roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
    379                                 : (ROSC *) malloc  ( sizeof(ROSC));
    380                 SC      = &roCheck[nroCheck++];
    381        
    382                 strcpy(SC->propName, b->name);
    383                 SC->perm = b->p;
    384         }
    385 
    386         fflush (stdout);
    387 }
    388 
    389 /* tell client to update an existing text vector property */
    390 void
    391 IDSetText (const ITextVectorProperty *tvp, const char *fmt, ...)
    392 {
    393         int i;
    394 
    395         xmlv1();
    396         printf ("<setTextVector\n");
    397         printf ("  device='%s'\n", tvp->device);
    398         printf ("  name='%s'\n", tvp->name);
    399         printf ("  state='%s'\n", pstateStr(tvp->s));
    400         printf ("  timeout='%g'\n", tvp->timeout);
    401         printf ("  timestamp='%s'\n", timestamp());
    402         if (fmt) {
    403             va_list ap;
    404             va_start (ap, fmt);
    405             printf ("  message='");
    406             vprintf (fmt, ap);
    407             printf ("'\n");
    408             va_end (ap);
    409         }
    410         printf (">\n");
    411 
    412         for (i = 0; i < tvp->ntp; i++) {
    413             IText *tp = &tvp->tp[i];
    414             printf ("  <oneText name='%s'>\n", tp->name);
    415             printf ("      %s\n", tp->text ? tp->text : "");
    416             printf ("  </oneText>\n");
    417         }
    418 
    419         printf ("</setTextVector>\n");
    420         fflush (stdout);
    421 }
    422 
    423 /* tell client to update an existing numeric vector property */
    424 void
    425 IDSetNumber (const INumberVectorProperty *nvp, const char *fmt, ...)
    426 {
    427         int i;
    428 
    429         xmlv1();
    430         printf ("<setNumberVector\n");
    431         printf ("  device='%s'\n", nvp->device);
    432         printf ("  name='%s'\n", nvp->name);
    433         printf ("  state='%s'\n", pstateStr(nvp->s));
    434         printf ("  timeout='%g'\n", nvp->timeout);
    435         printf ("  timestamp='%s'\n", timestamp());
    436         if (fmt) {
    437             va_list ap;
    438             va_start (ap, fmt);
    439             printf ("  message='");
    440             vprintf (fmt, ap);
    441             printf ("'\n");
    442             va_end (ap);
    443         }
    444         printf (">\n");
    445 
    446         for (i = 0; i < nvp->nnp; i++) {
    447             INumber *np = &nvp->np[i];
    448             printf ("  <oneNumber name='%s'>\n", np->name);
    449             printf ("      %.20g\n", np->value);
    450             printf ("  </oneNumber>\n");
    451         }
    452 
    453         printf ("</setNumberVector>\n");
    454         fflush (stdout);
    455 }
    456 
    457 /* tell client to update an existing switch vector property */
    458 void
    459 IDSetSwitch (const ISwitchVectorProperty *svp, const char *fmt, ...)
    460 {
    461         int i;
    462 
    463         xmlv1();
    464         printf ("<setSwitchVector\n");
    465         printf ("  device='%s'\n", svp->device);
    466         printf ("  name='%s'\n", svp->name);
    467         printf ("  state='%s'\n", pstateStr(svp->s));
    468         printf ("  timeout='%g'\n", svp->timeout);
    469         printf ("  timestamp='%s'\n", timestamp());
    470         if (fmt) {
    471             va_list ap;
    472             va_start (ap, fmt);
    473             printf ("  message='");
    474             vprintf (fmt, ap);
    475             printf ("'\n");
    476             va_end (ap);
    477         }
    478         printf (">\n");
    479 
    480         for (i = 0; i < svp->nsp; i++) {
    481             ISwitch *sp = &svp->sp[i];
    482             printf ("  <oneSwitch name='%s'>\n", sp->name);
    483             printf ("      %s\n", sstateStr(sp->s));
    484             printf ("  </oneSwitch>\n");
    485         }
    486 
    487         printf ("</setSwitchVector>\n");
    488         fflush (stdout);
    489 }
    490 
    491 /* tell client to update an existing lights vector property */
    492 void
    493 IDSetLight (const ILightVectorProperty *lvp, const char *fmt, ...)
    494 {
    495         int i;
    496 
    497         xmlv1();
    498         printf ("<setLightVector\n");
    499         printf ("  device='%s'\n", lvp->device);
    500         printf ("  name='%s'\n", lvp->name);
    501         printf ("  state='%s'\n", pstateStr(lvp->s));
    502         printf ("  timestamp='%s'\n", timestamp());
    503         if (fmt) {
    504             va_list ap;
    505             va_start (ap, fmt);
    506             printf ("  message='");
    507             vprintf (fmt, ap);
    508             printf ("'\n");
    509             va_end (ap);
    510         }
    511         printf (">\n");
    512 
    513         for (i = 0; i < lvp->nlp; i++) {
    514             ILight *lp = &lvp->lp[i];
    515             printf ("  <oneLight name='%s'>\n", lp->name);
    516             printf ("      %s\n", pstateStr(lp->s));
    517             printf ("  </oneLight>\n");
    518         }
    519 
    520         printf ("</setLightVector>\n");
    521         fflush (stdout);
    522 }
    523 
    524 /* tell client to update an existing BLOB vector property */
    525 void
    526 IDSetBLOB (const IBLOBVectorProperty *bvp, const char *fmt, ...)
    527 {
    528         int i;
    529 
    530         xmlv1();
    531         printf ("<setBLOBVector\n");
    532         printf ("  device='%s'\n", bvp->device);
    533         printf ("  name='%s'\n", bvp->name);
    534         printf ("  state='%s'\n", pstateStr(bvp->s));
    535         printf ("  timeout='%g'\n", bvp->timeout);
    536         printf ("  timestamp='%s'\n", timestamp());
    537         if (fmt) {
    538             va_list ap;
    539             va_start (ap, fmt);
    540             printf ("  message='");
    541             vprintf (fmt, ap);
    542             printf ("'\n");
    543             va_end (ap);
    544         }
    545         printf (">\n");
    546 
    547         for (i = 0; i < bvp->nbp; i++) {
    548             IBLOB *bp = &bvp->bp[i];
    549             unsigned char *encblob;
    550             int j, l;
    551 
    552             printf ("  <oneBLOB\n");
    553             printf ("    name='%s'\n", bp->name);
    554             printf ("    size='%d'\n", bp->size);
    555             printf ("    format='%s'>\n", bp->format);
    556 
    557             encblob = malloc (4*bp->bloblen/3+4);
    558             l = to64frombits(encblob, bp->blob, bp->bloblen);
    559             for (j = 0; j < l; j += 72)
    560                 printf ("%.72s\n", encblob+j);
    561             free (encblob);
    562 
    563             printf ("  </oneBLOB>\n");
    564         }
    565 
    566   printf ("</setBLOBVector>\n");
    567   fflush (stdout);
    568 }
    569 
    570 /* tell client to update min/max elements of an existing number vector property */
    571 void IUUpdateMinMax(const INumberVectorProperty *nvp)
    572 {
    573   int i;
    574 
    575   xmlv1();
    576   printf ("<setNumberVector\n");
    577   printf ("  device='%s'\n", nvp->device);
    578   printf ("  name='%s'\n", nvp->name);
    579   printf ("  state='%s'\n", pstateStr(nvp->s));
    580   printf ("  timeout='%g'\n", nvp->timeout);
    581   printf ("  timestamp='%s'\n", timestamp());
    582   printf (">\n");
    583 
    584   for (i = 0; i < nvp->nnp; i++) {
    585     INumber *np = &nvp->np[i];
    586     printf ("  <oneNumber name='%s'\n", np->name);
    587     printf ("    min='%g'\n", np->min);
    588     printf ("    max='%g'\n", np->max);
    589     printf ("    step='%g'\n", np->step);
    590     printf(">\n");
    591     printf ("      %g\n", np->value);
    592     printf ("  </oneNumber>\n");
    593   }
    594 
    595   printf ("</setNumberVector>\n");
    596   fflush (stdout);
    597 }
    598 
    599 /* send client a message for a specific device or at large if !dev */
    600 void
    601 IDMessage (const char *dev, const char *fmt, ...)
    602 {
    603 
    604         xmlv1();
    605         printf ("<message\n");
    606         if (dev)
    607             printf (" device='%s'\n", dev);
    608         printf ("  timestamp='%s'\n", timestamp());
    609         if (fmt) {
    610             va_list ap;
    611             va_start (ap, fmt);
    612             printf ("  message='");
    613             vprintf (fmt, ap);
    614             printf ("'\n");
    615             va_end (ap);
    616         }
    617         printf ("/>\n");
    618         fflush (stdout);
    619 }
    620 
    621 /* tell Client to delete the property with given name on given device, or
    622  * entire device if !name
    623  */
    624 void
    625 IDDelete (const char *dev, const char *name, const char *fmt, ...)
    626 {
    627         xmlv1();
    628         printf ("<delProperty\n  device='%s'\n", dev);
    629         if (name)
    630             printf (" name='%s'\n", name);
    631         printf ("  timestamp='%s'\n", timestamp());
    632         if (fmt) {
    633             va_list ap;
    634             va_start (ap, fmt);
    635             printf ("  message='");
    636             vprintf (fmt, ap);
    637             printf ("'\n");
    638             va_end (ap);
    639         }
    640         printf ("/>\n");
    641         fflush (stdout);
    642 }
    643 
    644 /* tell indiserver we want to snoop on the given device/property.
    645  * name ignored if NULL or empty.
    646  */
    647 void
    648 IDSnoopDevice (const char *snooped_device_name, char *snooped_property_name)
    649 {
    650         xmlv1();
    651         if (snooped_property_name && snooped_property_name[0])
    652             printf ("<getProperties device='%s' name='%s'/>\n",
    653                                     snooped_device_name, snooped_property_name);
    654         else
    655             printf ("<getProperties device='%s'/>\n", snooped_device_name);
    656         fflush (stdout);
    657 }
    658 
    659 /* tell indiserver whether we want BLOBs from the given snooped device.
    660  * silently ignored if given device is not already registered for snooping.
    661  */
    662 void
    663 IDSnoopBLOBs (const char *snooped_device, BLOBHandling bh)
    664 {
    665         const char *how;
    666 
    667         switch (bh) {
    668         case B_NEVER: how = "Never"; break;
    669         case B_ALSO:  how = "Also";  break;
    670         case B_ONLY:  how = "Only";  break;
    671         default: return;
    672         }
    673 
    674         xmlv1();
    675         printf ("<enableBLOB device='%s'>%s</enableBLOB>\n",
    676                                                 snooped_device, how);
    677         fflush (stdout);
    678 }
    679 
    680 /* "INDI" wrappers to the more generic eventloop facility. */
    681 
    682 int
    683 IEAddCallback (int readfiledes, IE_CBF *fp, void *p)
    684 {
    685         return (addCallback (readfiledes, (CBF*)fp, p));
    686 }
    687 
    688 void
    689 IERmCallback (int callbackid)
    690 {
    691         rmCallback (callbackid);
    692 }
    693 
    694 int
    695 IEAddTimer (int millisecs, IE_TCF *fp, void *p)
    696 {
    697         return (addTimer (millisecs, (TCF*)fp, p));
    698 }
    699 
    700 void
    701 IERmTimer (int timerid)
    702 {
    703         rmTimer (timerid);
    704 }
    705 
    706 int
    707 IEAddWorkProc (IE_WPF *fp, void *p)
    708 {
    709         return (addWorkProc ((WPF*)fp, p));
    710 }
    711 
    712 void
    713 IERmWorkProc (int workprocid)
    714 {
    715         rmWorkProc (workprocid);
    716 }
    717 
    718 
    719 int
    720 IEDeferLoop (int maxms, int *flagp)
    721 {
    722         return (deferLoop (maxms, flagp));
    723 }
    724 
    725 int
    726 IEDeferLoop0 (int maxms, int *flagp)
    727 {
    728         return (deferLoop0 (maxms, flagp));
    729 }
    730 
    731 /* find a member of an IText vector, else NULL */
    732 IText *
    733 IUFindText  (const ITextVectorProperty *tvp, const char *name)
    734 {
    735         int i;
    736 
    737         for (i = 0; i < tvp->ntp; i++)
    738             if (strcmp (tvp->tp[i].name, name) == 0)
    739                 return (&tvp->tp[i]);
    740         fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
    741         return (NULL);
    742 }
    743 
    744 /* find a member of an INumber vector, else NULL */
    745 INumber *
    746 IUFindNumber(const INumberVectorProperty *nvp, const char *name)
    747 {
    748         int i;
    749 
    750         for (i = 0; i < nvp->nnp; i++)
    751             if (strcmp (nvp->np[i].name, name) == 0)
    752                 return (&nvp->np[i]);
    753         fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
    754         return (NULL);
    755 }
    756 
    757 /* find a member of an ISwitch vector, else NULL */
    758 ISwitch *
    759 IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
    760 {
    761         int i;
    762 
    763         for (i = 0; i < svp->nsp; i++)
    764             if (strcmp (svp->sp[i].name, name) == 0)
    765                 return (&svp->sp[i]);
    766         fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
    767         return (NULL);
    768 }
    769 
    770 /* find an ON member of an ISwitch vector, else NULL.
    771  * N.B. user must make sense of result with ISRule in mind.
    772  */
    773 ISwitch *
    774 IUFindOnSwitch(const ISwitchVectorProperty *svp)
    775 {
    776         int i;
    777 
    778         for (i = 0; i < svp->nsp; i++)
    779             if (svp->sp[i].s == ISS_ON)
    780                 return (&svp->sp[i]);
    781         /*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
    782         return (NULL);
    783 }
    784 
    785 /* Set all switches to off */
    786 void
    787 IUResetSwitch(ISwitchVectorProperty *svp)
    788 {
    789   int i;
    790  
    791   for (i = 0; i < svp->nsp; i++)
    792     svp->sp[i].s = ISS_OFF;
    793 }
    794 
    795 /* Update property switches in accord with states and names. */
    796 int
    797 IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
    798 {
    799  int i=0;
    800  ISwitch *sp;
    801  char sn[MAXINDINAME];
    802 
    803  /* store On switch name */
    804  if (svp->r == ISR_1OFMANY)
    805  {
    806         sp = IUFindOnSwitch(svp);
    807         if (sp) strncpy(sn, sp->name, MAXINDINAME);
    808  
    809         IUResetSwitch(svp);
    810  }
    811  
    812  for (i = 0; i < n ; i++)
    813  {
    814    sp = IUFindSwitch(svp, names[i]);
    815          
    816    if (!sp)
    817    {
    818               svp->s = IPS_IDLE;
    819               IDSetSwitch(svp, "Error: %s is not a member of %s property.", names[i], svp->name);
    820               return -1;
    821    }
    822          
    823    sp->s = states[i];
    824  }
    825  
    826  /* Consistency checks for ISR_1OFMANY after update. */
    827  if (svp->r == ISR_1OFMANY)
    828  {
    829         int t_count=0;
    830         for (i=0; i < svp->nsp; i++)
    831         {
    832                 if (svp->sp[i].s == ISS_ON)
    833                         t_count++;
    834         }
    835         if (t_count != 1)
    836         {
    837                 IUResetSwitch(svp);
    838                 sp = IUFindSwitch(svp, sn);
    839                 if (sp) sp->s = ISS_ON;
    840                 svp->s = IPS_IDLE;
    841                 IDSetSwitch(svp, "Error: invalid state switch for property %s. %s.", svp->name, t_count == 0 ? "No switch is on" : "Too many switches are on");
    842                 return -1;
    843         }
    844  }
    845                
    846  return 0;
    847 
    848 }
    849 
    850 /* Update property numbers in accord with values and names */
    851 int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
    852 {
    853   int i=0;
    854  
    855   INumber *np;
    856  
    857   for (i = 0; i < n; i++)
    858   {
    859     np = IUFindNumber(nvp, names[i]);
    860     if (!np)
    861     {
    862         nvp->s = IPS_IDLE;
    863         IDSetNumber(nvp, "Error: %s is not a member of %s property.", names[i], nvp->name);
    864         return -1;
    865     }
    866    
    867     if (values[i] < np->min || values[i] > np->max)
    868     {
    869        nvp->s = IPS_IDLE;
    870        IDSetNumber(nvp, "Error: Invalid range. Valid range is from %g to %g", np->min, np->max);
    871        return -1;
    872     }
    873      
    874   }
    875 
    876   /* First loop checks for error, second loop set all values atomically*/
    877   for (i=0; i < n; i++)
    878   {
    879     np = IUFindNumber(nvp, names[i]);
    880     np->value = values[i];
    881   }
    882 
    883   return 0;
    884 
    885 }
    886 
    887 /* Update property text in accord with texts and names */
    888 int IUUpdateText(ITextVectorProperty *tvp, char * texts[], char *names[], int n)
    889 {
    890   int i=0;
    891  
    892   IText *tp;
    893  
    894   for (i = 0; i < n; i++)
    895   {
    896     tp = IUFindText(tvp, names[i]);
    897     if (!tp)
    898     {
    899         tvp->s = IPS_IDLE;
    900         IDSetText(tvp, "Error: %s is not a member of %s property.", names[i], tvp->name);
    901         return -1;
    902     }
    903   }
    904 
    905   /* First loop checks for error, second loop set all values atomically*/
    906   for (i=0; i < n; i++)
    907   {
    908     tp = IUFindText(tvp, names[i]);
    909     IUSaveText(tp, texts[i]);
    910   }
    911 
    912   return 0;
    913 
    914 }
    915 
    916 /* save malloced copy of newtext in tp->text, reusing if not first time */
    917 void
    918 IUSaveText (IText *tp, const char *newtext)
    919 {
    920         /* seed for realloc */
    921         if (tp->text == NULL)
    922             tp->text = malloc (1);
    923 
    924         /* copy in fresh string */
    925         tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
    926 }
    927 
    928 void IUFillSwitch(ISwitch *sp, const char *name, const char * label, ISState s)
    929 {
    930   strcpy(sp->name, name);
    931   strcpy(sp->label, label);
    932   sp->s = s;
    933   sp->svp = NULL;
    934   sp->aux = NULL;
    935 }
    936 
    937 void IUFillLight(ILight *lp, const char *name, const char * label, IPState s)
    938 {
    939   strcpy(lp->name, name);
    940   strcpy(lp->label, label);
    941   lp->s = s;
    942   lp->lvp = NULL;
    943   lp->aux = NULL;
    944 }
    945 
    946 
    947 void IUFillNumber(INumber *np, const char *name, const char * label, const char *format, double min, double max, double step, double value)
    948 {
    949 
    950   strcpy(np->name, name);
    951   strcpy(np->label, label);
    952   strcpy(np->format, format);
    953  
    954   np->min       = min;
    955   np->max       = max;
    956   np->step      = step;
    957   np->value     = value;
    958   np->nvp       = NULL;
    959   np->aux0      = NULL;
    960   np->aux1      = NULL;
    961 }
    962 
    963 void IUFillText(IText *tp, const char *name, const char * label, const char *initialText)
    964 {
    965 
    966   strcpy(tp->name, name);
    967   strcpy(tp->label, label);
    968   tp->text = NULL;
    969   tp->tvp  = NULL;
    970   tp->aux0 = NULL;
    971   tp->aux1 = NULL;
    972 
    973   IUSaveText(tp, initialText);
    974 
    975 }
    976 
    977 void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char * dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
    978 {
    979   strcpy(svp->device, dev);
    980   strcpy(svp->name, name);
    981   strcpy(svp->label, label);
    982   strcpy(svp->group, group);
    983   strcpy(svp->timestamp, "");
    984  
    985   svp->p        = p;
    986   svp->r        = r;
    987   svp->timeout  = timeout;
    988   svp->s        = s;
    989   svp->sp       = sp;
    990   svp->nsp      = nsp;
    991 }
    992 
    993 void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char * dev, const char *name, const char *label, const char *group, IPState s)
    994 {
    995   strcpy(lvp->device, dev);
    996   strcpy(lvp->name, name);
    997   strcpy(lvp->label, label);
    998   strcpy(lvp->group, group);
    999   strcpy(lvp->timestamp, "");
    1000  
    1001   lvp->s        = s;
    1002   lvp->lp       = lp;
    1003   lvp->nlp      = nlp;
    1004 }
    1005  
    1006 void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s)
    1007 {
    1008  
    1009   strcpy(nvp->device, dev);
    1010   strcpy(nvp->name, name);
    1011   strcpy(nvp->label, label);
    1012   strcpy(nvp->group, group);
    1013   strcpy(nvp->timestamp, "");
    1014  
    1015   nvp->p        = p;
    1016   nvp->timeout  = timeout;
    1017   nvp->s        = s;
    1018   nvp->np       = np;
    1019   nvp->nnp      = nnp;
    1020  
    1021 }
    1022 
    1023 void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s)
    1024 {
    1025   strcpy(tvp->device, dev);
    1026   strcpy(tvp->name, name);
    1027   strcpy(tvp->label, label);
    1028   strcpy(tvp->group, group);
    1029   strcpy(tvp->timestamp, "");
    1030  
    1031   tvp->p        = p;
    1032   tvp->timeout  = timeout;
    1033   tvp->s        = s;
    1034   tvp->tp       = tp;
    1035   tvp->ntp      = ntp;
    1036 
    1037 }
    1038 
    1039 /*****************************************************************************
    1040  * convenience functions for use in your implementation of ISSnoopDevice().
    1041  */
    1042 
    1043 /* crack the snooped driver setNumberVector or defNumberVector message into
    1044  * the given INumberVectorProperty.
    1045  * return 0 if type, device and name match and all members are present, else
    1046  * return -1
    1047  */
    1048 int
    1049 IUSnoopNumber (XMLEle *root, INumberVectorProperty *nvp)
    1050 {
    1051         char *dev, *name;
    1052         XMLEle *ep;
    1053         int i;
    1054 
    1055         /* check and crack type, device, name and state */
    1056         if (strcmp (tagXMLEle(root)+3, "NumberVector") ||
    1057                                         crackDN (root, &dev, &name, NULL) < 0)
    1058             return (-1);
    1059         if (strcmp (dev, nvp->device) || strcmp (name, nvp->name))
    1060             return (-1);        /* not this property */
    1061         (void) crackIPState (findXMLAttValu (root,"state"), &nvp->s);
    1062 
    1063         /* match each INumber with a oneNumber */
    1064         for (i = 0; i < nvp->nnp; i++) {
    1065             for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1066                 if (!strcmp (tagXMLEle(ep), "oneNumber") &&
    1067                         !strcmp (nvp->np[i].name, findXMLAttValu(ep, "name"))) {
    1068                     if (f_scansexa (pcdataXMLEle(ep), &nvp->np[i].value) < 0)
    1069                         return (-1);    /* bad number format */
    1070                     break;
    1071                 }
    1072             }
    1073             if (!ep)
    1074                 return (-1);    /* element not found */
    1075         }
    1076 
    1077         /* ok */
    1078         return (0);
    1079 }
    1080 
    1081 /* crack the snooped driver setTextVector or defTextVector message into
    1082  * the given ITextVectorProperty.
    1083  * return 0 if type, device and name match and all members are present, else
    1084  * return -1
    1085  */
    1086 int
    1087 IUSnoopText (XMLEle *root, ITextVectorProperty *tvp)
    1088 {
    1089         char *dev, *name;
    1090         XMLEle *ep;
    1091         int i;
    1092 
    1093         /* check and crack type, device, name and state */
    1094         if (strcmp (tagXMLEle(root)+3, "TextVector") ||
    1095                                         crackDN (root, &dev, &name, NULL) < 0)
    1096             return (-1);
    1097         if (strcmp (dev, tvp->device) || strcmp (name, tvp->name))
    1098             return (-1);        /* not this property */
    1099         (void) crackIPState (findXMLAttValu (root,"state"), &tvp->s);
    1100 
    1101         /* match each IText with a oneText */
    1102         for (i = 0; i < tvp->ntp; i++) {
    1103             for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1104                 if (!strcmp (tagXMLEle(ep), "oneText") &&
    1105                         !strcmp (tvp->tp[i].name, findXMLAttValu(ep, "name"))) {
    1106                     IUSaveText (&tvp->tp[i], pcdataXMLEle(ep));
    1107                     break;
    1108                 }
    1109             }
    1110             if (!ep)
    1111                 return (-1);    /* element not found */
    1112         }
    1113 
    1114         /* ok */
    1115         return (0);
    1116 }
    1117 
    1118 /* crack the snooped driver setLightVector or defLightVector message into
    1119  * the given ILightVectorProperty. it is not necessary that all ILight names
    1120  * be found.
    1121  * return 0 if type, device and name match, else return -1.
    1122  */
    1123 int
    1124 IUSnoopLight (XMLEle *root, ILightVectorProperty *lvp)
    1125 {
    1126         char *dev, *name;
    1127         XMLEle *ep;
    1128         int i;
    1129 
    1130         /* check and crack type, device, name and state */
    1131         if (strcmp (tagXMLEle(root)+3, "LightVector") ||
    1132                                         crackDN (root, &dev, &name, NULL) < 0)
    1133             return (-1);
    1134         if (strcmp (dev, lvp->device) || strcmp (name, lvp->name))
    1135             return (-1);        /* not this property */
    1136 
    1137         (void) crackIPState (findXMLAttValu (root,"state"), &lvp->s);
    1138 
    1139         /* match each oneLight with one ILight */
    1140         for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1141             if (!strcmp (tagXMLEle(ep), "oneLight")) {
    1142                 const char *name = findXMLAttValu (ep, "name");
    1143                 for (i = 0; i < lvp->nlp; i++) {
    1144                     if (!strcmp (lvp->lp[i].name, name)) {
    1145                         if (crackIPState(pcdataXMLEle(ep), &lvp->lp[i].s) < 0) {
    1146                             return (-1);        /* unrecognized state */
    1147                         }
    1148                         break;
    1149                     }
    1150                 }
    1151             }
    1152         }
    1153 
    1154         /* ok */
    1155         return (0);
    1156 }
    1157 
    1158 /* crack the snooped driver setSwitchVector or defSwitchVector message into the
    1159  * given ISwitchVectorProperty. it is not necessary that all ISwitch names be
    1160  * found.
    1161  * return 0 if type, device and name match, else return -1.
    1162  */
    1163 int
    1164 IUSnoopSwitch (XMLEle *root, ISwitchVectorProperty *svp)
    1165 {
    1166         char *dev, *name;
    1167         XMLEle *ep;
    1168         int i;
    1169 
    1170         /* check and crack type, device, name and state */
    1171         if (strcmp (tagXMLEle(root)+3, "SwitchVector") ||
    1172                                         crackDN (root, &dev, &name, NULL) < 0)
    1173             return (-1);
    1174         if (strcmp (dev, svp->device) || strcmp (name, svp->name))
    1175             return (-1);        /* not this property */
    1176         (void) crackIPState (findXMLAttValu (root,"state"), &svp->s);
    1177 
    1178         /* match each oneSwitch with one ISwitch */
    1179         for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1180             if (!strcmp (tagXMLEle(ep), "oneSwitch")) {
    1181                 const char *name = findXMLAttValu (ep, "name");
    1182                 for (i = 0; i < svp->nsp; i++) {
    1183                     if (!strcmp (svp->sp[i].name, name)) {
    1184                         if (crackISState(pcdataXMLEle(ep), &svp->sp[i].s) < 0) {
    1185                             return (-1);        /* unrecognized state */
    1186                         }
    1187                         break;
    1188                     }
    1189                 }
    1190             }
    1191         }
    1192 
    1193         /* ok */
    1194         return (0);
    1195 }
    1196 
    1197 /* crack the snooped driver setBLOBVector message into the given
    1198  * IBLOBVectorProperty. it is not necessary that all IBLOB names be found.
    1199  * return 0 if type, device and name match, else return -1.
    1200  * N.B. we assume any existing blob in bvp has been malloced, which we free
    1201  *   and replace with a newly malloced blob if found.
    1202  */
    1203 int
    1204 IUSnoopBLOB (XMLEle *root, IBLOBVectorProperty *bvp)
    1205 {
    1206         char *dev, *name;
    1207         XMLEle *ep;
    1208         int i;
    1209 
    1210         /* check and crack type, device, name and state */
    1211         if (strcmp (tagXMLEle(root), "setBLOBVector") ||
    1212                                         crackDN (root, &dev, &name, NULL) < 0)
    1213             return (-1);
    1214         if (strcmp (dev, bvp->device) || strcmp (name, bvp->name))
    1215             return (-1);        /* not this property */
    1216         (void) crackIPState (findXMLAttValu (root,"state"), &bvp->s);
    1217 
    1218         /* match each oneBLOB with one IBLOB */
    1219         for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1220             if (!strcmp (tagXMLEle(ep), "oneBLOB")) {
    1221                 const char *name = findXMLAttValu (ep, "name");
    1222                 for (i = 0; i < bvp->nbp; i++) {
    1223                     IBLOB *bp = &bvp->bp[i];
    1224                     if (!strcmp (bp->name, name)) {
    1225                         strcpy (bp->format, findXMLAttValu (ep,"format"));
    1226                         bp->size = atof (findXMLAttValu (ep,"size"));
    1227                         bp->bloblen = pcdatalenXMLEle(ep)+1;
    1228                         if (bp->blob)
    1229                             free (bp->blob);
    1230                         bp->blob = strcpy(malloc(bp->bloblen),pcdataXMLEle(ep));
    1231                         break;
    1232                     }
    1233                 }
    1234             }
    1235         }
    1236 
    1237         /* ok */
    1238         return (0);
    1239 }
    1240 
    1241 /* print usage message and exit (1) */
    1242 static void
    1243 usage(void)
    1244 {
    1245         fprintf (stderr, "Usage: %s [options]\n", me);
    1246         fprintf (stderr, "Purpose: INDI Device driver framework.\n");
    1247         fprintf (stderr, "Options:\n");
    1248         fprintf (stderr, " -v    : more verbose to stderr\n");
    1249 
    1250         exit (1);
    1251 }
    1252 
    1253 /* callback when INDI client message arrives on stdin.
    1254  * collect and dispatch when see outter element closure.
    1255  * exit if OS trouble or see incompatable INDI version.
    1256  * arg is not used.
    1257  */
    1258 static void
    1259 clientMsgCB (int fd, void *arg)
    1260 {
    1261         char buf[1024], msg[1024], *bp;
    1262         int nr;
    1263         arg=arg;
    1264 
    1265         /* one read */
    1266         nr = read (fd, buf, sizeof(buf));
    1267         if (nr < 0) {
    1268             fprintf (stderr, "%s: %s\n", me, strerror(errno));
    1269             exit(1);
    1270         }
    1271         if (nr == 0) {
    1272             fprintf (stderr, "%s: EOF\n", me);
    1273             exit(1);
    1274         }
    1275 
    1276         /* crack and dispatch when complete */
    1277         for (bp = buf; nr-- > 0; bp++) {
    1278             XMLEle *root = readXMLEle (clixml, *bp, msg);
    1279             if (root) {
    1280                 if (dispatch (root, msg) < 0)
    1281                     fprintf (stderr, "%s dispatch error: %s\n", me, msg);
    1282                 delXMLEle (root);
    1283             } else if (msg[0])
    1284                 fprintf (stderr, "%s XML error: %s\n", me, msg);
    1285         }
    1286 
    1287 }
    1288 
    1289 /* crack the given INDI XML element and call driver's IS* entry points as they
    1290  *   are recognized.
    1291  * return 0 if ok else -1 with reason in msg[].
    1292  * N.B. exit if getProperties does not proclaim a compatible version.
    1293  */
    1294 static int
    1295 dispatch (XMLEle *root, char msg[])
    1296 {
    1297         char *rtag = tagXMLEle(root);
    1298         XMLEle *ep;
    1299         int n,i=0;
    1300 
    1301         if (verbose)
    1302             prXMLEle (stderr, root, 0);
    1303 
    1304         /* check tag in surmised decreasing order of likelyhood */
    1305 
    1306         if (!strcmp (rtag, "newNumberVector")) {
    1307             static double *doubles;
    1308             static char **names;
    1309             static int maxn;
    1310             char *dev, *name;
    1311 
    1312             /* pull out device and name */
    1313             if (crackDN (root, &dev, &name, msg) < 0)
    1314                 return (-1);
    1315 
    1316             /* seed for reallocs */
    1317             if (!doubles) {
    1318                 doubles = (double *) malloc (1);
    1319                 names = (char **) malloc (1);
    1320             }
    1321 
    1322             /* pull out each name/value pair */
    1323             for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1324                 if (strcmp (tagXMLEle(ep), "oneNumber") == 0) {
    1325                     XMLAtt *na = findXMLAtt (ep, "name");
    1326                     if (na) {
    1327                         if (n >= maxn) {
    1328                             /* grow for this and another */
    1329                             int newsz = (maxn=n+1)*sizeof(double);
    1330                             doubles = (double *) realloc(doubles,newsz);
    1331                             newsz = maxn*sizeof(char *);
    1332                             names = (char **) realloc (names, newsz);
    1333                         }
    1334                         if (f_scansexa (pcdataXMLEle(ep), &doubles[n]) < 0)
    1335                             IDMessage (dev,"%s: Bad format %s", name,
    1336                                                             pcdataXMLEle(ep));
    1337                         else
    1338                             names[n++] = valuXMLAtt(na);
    1339                     }
    1340                 }
    1341             }
    1342            
    1343             /* insure property is not RO */
    1344             for (i=0; i < nroCheck; i++)
    1345             {
    1346               if (!strcmp(roCheck[i].propName, name))
    1347               {
    1348                if (roCheck[i].perm == IP_RO)
    1349                  return -1;
    1350               }
    1351             }
    1352 
    1353             /* invoke driver if something to do, but not an error if not */
    1354             if (n > 0)
    1355                 ISNewNumber (dev, name, doubles, names, n);
    1356             else
    1357                 IDMessage(dev,"%s: newNumberVector with no valid members",name);
    1358             return (0);
    1359         }
    1360 
    1361         if (!strcmp (rtag, "newSwitchVector")) {
    1362             static ISState *states;
    1363             static char **names;
    1364             static int maxn;
    1365             char *dev, *name;
    1366             XMLEle *ep;
    1367 
    1368             /* pull out device and name */
    1369             if (crackDN (root, &dev, &name, msg) < 0)
    1370                 return (-1);
    1371 
    1372             /* seed for reallocs */
    1373             if (!states) {
    1374                 states = (ISState *) malloc (1);
    1375                 names = (char **) malloc (1);
    1376             }
    1377 
    1378             /* pull out each name/state pair */
    1379             for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1380                 if (strcmp (tagXMLEle(ep), "oneSwitch") == 0) {
    1381                     XMLAtt *na = findXMLAtt (ep, "name");
    1382                     if (na) {
    1383                         if (n >= maxn) {
    1384                             int newsz = (maxn=n+1)*sizeof(ISState);
    1385                             states = (ISState *) realloc(states, newsz);
    1386                             newsz = maxn*sizeof(char *);
    1387                             names = (char **) realloc (names, newsz);
    1388                         }
    1389                         if (strcmp (pcdataXMLEle(ep),"On") == 0) {
    1390                             states[n] = ISS_ON;
    1391                             names[n] = valuXMLAtt(na);
    1392                             n++;
    1393                         } else if (strcmp (pcdataXMLEle(ep),"Off") == 0) {
    1394                             states[n] = ISS_OFF;
    1395                             names[n] = valuXMLAtt(na);
    1396                             n++;
    1397                         } else
    1398                             IDMessage (dev, "%s: must be On or Off: %s", name,
    1399                                                             pcdataXMLEle(ep));
    1400                     }
    1401                 }
    1402             }
    1403 
    1404             /* insure property is not RO */
    1405             for (i=0; i < nroCheck; i++)
    1406             {
    1407               if (!strcmp(roCheck[i].propName, name))
    1408               {
    1409                if (roCheck[i].perm == IP_RO)
    1410                  return -1;
    1411               }
    1412             }
    1413            
    1414             /* invoke driver if something to do, but not an error if not */
    1415             if (n > 0)
    1416                 ISNewSwitch (dev, name, states, names, n);
    1417             else
    1418                 IDMessage(dev,"%s: newSwitchVector with no valid members",name);
    1419             return (0);
    1420         }
    1421 
    1422         if (!strcmp (rtag, "newTextVector")) {
    1423             static char **texts;
    1424             static char **names;
    1425             static int maxn;
    1426             char *dev, *name;
    1427 
    1428             /* pull out device and name */
    1429             if (crackDN (root, &dev, &name, msg) < 0)
    1430                 return (-1);
    1431 
    1432             /* seed for reallocs */
    1433             if (!texts) {
    1434                 texts = (char **) malloc (1);
    1435                 names = (char **) malloc (1);
    1436             }
    1437 
    1438             /* pull out each name/text pair */
    1439             for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1440                 if (strcmp (tagXMLEle(ep), "oneText") == 0) {
    1441                     XMLAtt *na = findXMLAtt (ep, "name");
    1442                     if (na) {
    1443                         if (n >= maxn) {
    1444                             int newsz = (maxn=n+1)*sizeof(char *);
    1445                             texts = (char **) realloc (texts, newsz);
    1446                             names = (char **) realloc (names, newsz);
    1447                         }
    1448                         texts[n] = pcdataXMLEle(ep);
    1449                         names[n] = valuXMLAtt(na);
    1450                         n++;
    1451                     }
    1452                 }
    1453             }
    1454            
    1455             /* insure property is not RO */
    1456             for (i=0; i < nroCheck; i++)
    1457             {
    1458               if (!strcmp(roCheck[i].propName, name))
    1459               {
    1460                if (roCheck[i].perm == IP_RO)
    1461                  return -1;
    1462               }
    1463             }
    1464 
    1465             /* invoke driver if something to do, but not an error if not */
    1466             if (n > 0)
    1467                 ISNewText (dev, name, texts, names, n);
    1468             else
    1469                 IDMessage (dev, "%s: set with no valid members", name);
    1470             return (0);
    1471         }
    1472 
    1473         if (!strcmp (rtag, "newBLOBVector")) {
    1474             static char **blobs;
    1475             static char **names;
    1476             static char **formats;
    1477             static int *blobsizes;
    1478             static int *sizes;
    1479             static int maxn;
    1480             char *dev, *name;
    1481             int i;
    1482 
    1483             /* pull out device and name */
    1484             if (crackDN (root, &dev, &name, msg) < 0)
    1485                 return (-1);
    1486 
    1487             /* seed for reallocs */
    1488             if (!blobs) {
    1489                 blobs = (char **) malloc (1);
    1490                 names = (char **) malloc (1);
    1491                 formats = (char **) malloc (1);
    1492                 blobsizes = (int *) malloc (1);
    1493                 sizes = (int *) malloc (1);
    1494             }
    1495 
    1496             /* pull out each name/BLOB pair, decode */
    1497             for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
    1498                 if (strcmp (tagXMLEle(ep), "oneBLOB") == 0) {
    1499                     XMLAtt *na = findXMLAtt (ep, "name");
    1500                     XMLAtt *fa = findXMLAtt (ep, "format");
    1501                     XMLAtt *sa = findXMLAtt (ep, "size");
    1502                     if (na && fa && sa) {
    1503                         if (n >= maxn) {
    1504                             int newsz = (maxn=n+1)*sizeof(char *);
    1505                             blobs = (char **) realloc (blobs, newsz);
    1506                             names = (char **) realloc (names, newsz);
    1507                             formats = (char **) realloc(formats,newsz);
    1508                             newsz = maxn*sizeof(int);
    1509                             sizes = (int *) realloc(sizes,newsz);
    1510                             blobsizes = (int *) realloc(blobsizes,newsz);
    1511                         }
    1512                         blobs[n] = malloc (3*pcdatalenXMLEle(ep)/4);
    1513                         blobsizes[n] = from64tobits(blobs[n], pcdataXMLEle(ep));
    1514                         names[n] = valuXMLAtt(na);
    1515                         formats[n] = valuXMLAtt(fa);
    1516                         sizes[n] = atoi(valuXMLAtt(sa));
    1517                         n++;
    1518                     }
    1519                 }
    1520             }
    1521 
    1522             /* invoke driver if something to do, but not an error if not */
    1523             if (n > 0) {
    1524                 ISNewBLOB (dev, name, sizes, blobsizes, blobs, formats,names,n);
    1525                 for (i = 0; i < n; i++)
    1526                     free (blobs[i]);
    1527             } else
    1528                 IDMessage (dev, "%s: newBLOBVector with no valid members",name);
    1529             return (0);
    1530         }
    1531 
    1532         if (!strcmp (rtag, "getProperties")) {
    1533             XMLAtt *ap;
    1534             double v;
    1535 
    1536             /* check version */
    1537             ap = findXMLAtt (root, "version");
    1538             if (!ap) {
    1539                 fprintf (stderr, "%s: getProperties missing version\n", me);
    1540                 exit(1);
    1541             }
    1542             v = atof (valuXMLAtt(ap));
    1543             if (v > INDIV) {
    1544                 fprintf (stderr, "%s: client version %g > %g\n", me, v, INDIV);
    1545                 exit(1);
    1546             }
    1547 
    1548             /* ok */
    1549             ap = findXMLAtt (root, "device");
    1550             ISGetProperties (ap ? valuXMLAtt(ap) : NULL);
    1551             return (0);
    1552         }
    1553 
    1554         /* other commands might be from a snooped device.
    1555          * we don't know here which devices are being snooped so we send
    1556          * all remaining valid messages
    1557          */
    1558         if (        !strcmp (rtag, "setNumberVector") ||
    1559                     !strcmp (rtag, "setTextVector") ||
    1560                     !strcmp (rtag, "setLightVector") ||
    1561                     !strcmp (rtag, "setSwitchVector") ||
    1562                     !strcmp (rtag, "setBLOBVector") ||
    1563                     !strcmp (rtag, "defNumberVector") ||
    1564                     !strcmp (rtag, "defTextVector") ||
    1565                     !strcmp (rtag, "defLightVector") ||
    1566                     !strcmp (rtag, "defSwitchVector") ||
    1567                     !strcmp (rtag, "defBLOBVector") ||
    1568                     !strcmp (rtag, "message") ||
    1569                     !strcmp (rtag, "delProperty")) {
    1570             ISSnoopDevice (root);
    1571             return (0);
    1572         }
    1573 
    1574         sprintf (msg, "Unknown command: %s", rtag);
    1575         return(1);
    1576 }
    1577 
    1578 /* pull out device and name attributes from root.
    1579  * return 0 if ok else -1 with reason in msg[].
    1580  */
    1581 static int
    1582 crackDN (XMLEle *root, char **dev, char **name, char msg[])
    1583 {
    1584         XMLAtt *ap;
    1585 
    1586         ap = findXMLAtt (root, "device");
    1587         if (!ap) {
    1588             sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
    1589             return (-1);
    1590         }
    1591         *dev = valuXMLAtt(ap);
    1592 
    1593         ap = findXMLAtt (root, "name");
    1594         if (!ap) {
    1595             sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
    1596             return (-1);
    1597         }
    1598         *name = valuXMLAtt(ap);
    1599 
    1600         return (0);
    1601 }
    1602 
    1603 /* return static string corresponding to the given property or light state */
    1604 const char *
    1605 pstateStr (IPState s)
    1606 {
    1607         switch (s) {
    1608         case IPS_IDLE:  return ("Idle");
    1609         case IPS_OK:    return ("Ok");
    1610         case IPS_BUSY:  return ("Busy");
    1611         case IPS_ALERT: return ("Alert");
    1612         default:
    1613             fprintf (stderr, "Impossible IPState %d\n", s);
    1614             exit(1);
    1615         }
    1616 }
    1617 
    1618 /* crack string into IPState.
    1619  * return 0 if ok, else -1
    1620  */
    1621 static int
    1622 crackIPState (const char *str, IPState *ip)
    1623 {
    1624              if (!strcmp (str, "Idle"))  *ip = IPS_IDLE;
    1625         else if (!strcmp (str, "Ok"))    *ip = IPS_OK;
    1626         else if (!strcmp (str, "Busy"))  *ip = IPS_BUSY;
    1627         else if (!strcmp (str, "Alert")) *ip = IPS_ALERT;
    1628         else return (-1);
    1629         return (0);
    1630 }
    1631 
    1632 /* crack string into ISState.
    1633  * return 0 if ok, else -1
    1634  */
    1635 static int
    1636 crackISState (const char *str, ISState *ip)
    1637 {
    1638              if (!strcmp (str, "On"))  *ip = ISS_ON;
    1639         else if (!strcmp (str, "Off")) *ip = ISS_OFF;
    1640         else return (-1);
    1641         return (0);
    1642 }
    1643 
    1644 /* return static string corresponding to the given switch state */
    1645 const char *
    1646 sstateStr (ISState s)
    1647 {
    1648         switch (s) {
    1649         case ISS_ON:  return ("On");
    1650         case ISS_OFF: return ("Off");
    1651         default:
    1652             fprintf (stderr, "Impossible ISState %d\n", s);
    1653             exit(1);
    1654         }
    1655 }
    1656 
    1657 /* return static string corresponding to the given Rule */
    1658 const char *
    1659 ruleStr (ISRule r)
    1660 {
    1661         switch (r) {
    1662         case ISR_1OFMANY: return ("OneOfMany");
    1663         case ISR_ATMOST1: return ("AtMostOne");
    1664         case ISR_NOFMANY: return ("AnyOfMany");
    1665         default:
    1666             fprintf (stderr, "Impossible ISRule %d\n", r);
    1667             exit(1);
    1668         }
    1669 }
    1670 
    1671 /* return static string corresponding to the given IPerm */
    1672 const char *
    1673 permStr (IPerm p)
    1674 {
    1675         switch (p) {
    1676         case IP_RO: return ("ro");
    1677         case IP_WO: return ("wo");
    1678         case IP_RW: return ("rw");
    1679         default:
    1680             fprintf (stderr, "Impossible IPerm %d\n", p);
    1681             exit(1);
    1682         }
    1683 }
    1684 
    1685 /* print the boilerplate comment introducing xml */
    1686 static void
    1687 xmlv1()
    1688 {
    1689         printf ("<?xml version='1.0'?>\n");
    1690 }
  • BAORadio/libindi/libindi/indiserver.c

    r490 r501  
    9292} Snoopee;
    9393
     94struct
     95{
     96    const char *name;                      /* Path to FIFO for dynamic startups & shutdowns of drivers */
     97    int fd;
     98    FILE *fs;
     99} fifo;
     100
    94101/* info for each connected client */
    95102typedef struct {
     
    109116/* info for each connected driver */
    110117typedef struct {
    111     const char *name;                           /* persistent malloced name */
     118    char name[MAXINDIDEVICE];           /* persistent name */
    112119    char dev[MAXINDIDEVICE];            /* device served by this driver */
     120    int active;                         /* 1 when this record is in use */
    113121    Snoopee *sprops;                    /* malloced array of props we snoop */
    114122    int nsprops;                        /* n entries in sprops[] */
     
    136144static void noZombies (void);
    137145static void noSIGPIPE (void);
     146static void indiFIFO(void);
    138147static void indiRun (void);
    139148static void indiListen (void);
     149static void newFIFO(void);
    140150static void newClient (void);
    141151static int newClSocket (void);
     
    146156static void startRemoteDvr (DvrInfo *dp);
    147157static int openINDIServer (char host[], int indi_port);
    148 static void restartDvr (DvrInfo *dp);
     158static void shutdownDvr (DvrInfo *dp, int restart);
    149159static void q2RDrivers (const char *dev, Msg *mp, XMLEle *root);
    150160static void q2SDrivers (int isblob, const char *dev, const char *name, Msg *mp,
     
    209219                    ac--;
    210220                    break;
     221                case 'f':
     222                    if (ac < 2) {
     223                        fprintf (stderr, "-f requires fifo node\n");
     224                        usage();
     225                    }
     226                    fifo.name = *++av;
     227                    ac--;
     228                    break;
    211229                case 'v':
    212230                    verbose++;
     
    218236
    219237        /* at this point there are ac args in av[] to name our drivers */
    220         if (ac == 0)
    221             usage();
     238        if (ac == 0 && !fifo.name)
     239            usage();
    222240
    223241        /* take care of some unixisms */
     
    230248
    231249        /* create driver info array all at once since size never changes */
    232         ndvrinfo = ac;
     250        ndvrinfo = ac;
    233251        dvrinfo = (DvrInfo *) calloc (ndvrinfo, sizeof(DvrInfo));
    234252
    235253        /* start each driver */
    236         while (ac-- > 0) {
    237             dvrinfo[ac].name = *av++;
     254        while (ac-- > 0) {
     255            strcpy(dvrinfo[ac].name, *av++);
    238256            startDvr (&dvrinfo[ac]);
    239         }
     257        }
    240258
    241259        /* announce we are online */
    242260        indiListen();
     261
     262        /* Load up FIFO, if available */
     263        indiFIFO();
    243264
    244265        /* handle new clients and all io */
     
    271292        fprintf (stderr, "Code %s. Protocol %g.\n", "$Revision: 726523 $", INDIV);
    272293        fprintf (stderr, "Options:\n");
    273         fprintf (stderr, " -l d  : log driver messages to <d>/YYYY-MM-DD.islog\n");
    274         fprintf (stderr, " -m m  : kill client if gets more than this many MB behind, default %d\n", DEFMAXQSIZ);
    275         fprintf (stderr, " -p p  : alternate IP port, default %d\n", INDIPORT);
    276         fprintf (stderr, " -v    : show key events, no traffic\n");
    277         fprintf (stderr, " -vv   : -v + key message content\n");
    278         fprintf (stderr, " -vvv  : -vv + complete xml\n");
    279         fprintf (stderr, "driver : executable or device@host[:port]\n");
     294        fprintf (stderr, " -l d     : log driver messages to <d>/YYYY-MM-DD.islog\n");
     295        fprintf (stderr, " -m m     : kill client if gets more than this many MB behind, default %d\n", DEFMAXQSIZ);
     296        fprintf (stderr, " -p p     : alternate IP port, default %d\n", INDIPORT);
     297        fprintf (stderr, " -f path  : Path to fifo for dynamic startup and shutdown of drivers.\n");
     298        fprintf (stderr, " -v       : show key events, no traffic\n");
     299        fprintf (stderr, " -vv      : -v + key message content\n");
     300        fprintf (stderr, " -vvv     : -vv + complete xml\n");
     301        fprintf (stderr, "driver    : executable or device@host[:port]\n");
    280302
    281303        exit (2);
     
    307329}
    308330
     331static DvrInfo * allocDvr ()
     332{
     333    DvrInfo *dp = NULL;
     334    int dvi;
     335
     336/* try to reuse a drivber slot, else add one */
     337for (dvi = 0; dvi < ndvrinfo; dvi++)
     338    if (!(dp = &dvrinfo[dvi])->active)
     339        break;
     340if (dvi == ndvrinfo)
     341{
     342    /* grow dvrinfo */
     343    dvrinfo = (DvrInfo *) realloc (dvrinfo, (ndvrinfo+1)*sizeof(DvrInfo));
     344    if (!dvrinfo) {
     345        fprintf (stderr, "no memory for new drivers\n");
     346        Bye();
     347    }
     348    dp = &dvrinfo[ndvrinfo++];
     349}
     350
     351/* rig up new dvrinfo entry */
     352memset (dp, 0, sizeof(*dp));
     353dp->active = 1;
     354
     355return dp;
     356
     357}
     358
    309359/* start the given INDI driver process or connection.
    310360 * exit if trouble.
     
    382432        dp->efd = ep[0];
    383433        dp->lp = newLilXML();
    384         dp->msgq = newFQ(1);
     434        dp->msgq = newFQ(1);
    385435        dp->sprops = (Snoopee*) malloc (1);     /* seed for realloc */
    386436        dp->nsprops = 0;
    387437        dp->nsent = 0;
     438        dp->active = 1;
    388439
    389440        /* first message primes driver to report its properties -- dev known
     
    436487        dp->nsprops = 0;
    437488        dp->nsent = 0;
     489        dp->active = 1;
    438490
    439491        /* N.B. storing name now is key to limiting outbound traffic to this
     
    544596}
    545597
     598/* Attempt to open up FIFO */
     599static void indiFIFO(void)
     600{
     601    /* Open up FIFO, if available */
     602    if (fifo.name)
     603    {
     604        fifo.fd = open(fifo.name, O_RDONLY);
     605                  if (fifo.fd < 0)
     606                  {
     607                       fprintf(stderr, "%s: open(%s): %s.\n", indi_tstamp(NULL), fifo.name, strerror(errno));
     608                        Bye();
     609                   }
     610
     611        fifo.fs = fdopen(fifo.fd, "r");
     612    }
     613}
     614
    546615/* service traffic from clients and drivers */
    547616static void
     
    549618{
    550619        fd_set rs, ws;
    551         int maxfd;
     620        int maxfd=0;
    552621        int i, s;
    553622
     
    556625        FD_ZERO(&rs);
    557626
     627        if (fifo.name && fifo.fd > 0)
     628        {
     629           FD_SET(fifo.fd, &rs);
     630           maxfd = fifo.fd;
     631        }
     632
    558633        /* always listen for new clients */
    559634        FD_SET(lsocket, &rs);
    560         maxfd = lsocket;
     635        if (lsocket > maxfd)
     636                maxfd = lsocket;
    561637
    562638        /* add all client readers and client writers with work to send */
     
    573649
    574650        /* add all driver readers and driver writers with work to send */
    575         for (i = 0; i < ndvrinfo; i++) {
     651        for (i = 0; i < ndvrinfo; i++)
     652        {
    576653            DvrInfo *dp = &dvrinfo[i];
    577             FD_SET(dp->rfd, &rs);
    578             if (dp->rfd > maxfd)
    579                 maxfd = dp->rfd;
    580             if (dp->pid != REMOTEDVR) {
    581                 FD_SET(dp->efd, &rs);
    582                 if (dp->efd > maxfd)
    583                     maxfd = dp->efd;
    584             }
    585             if (nFQ(dp->msgq) > 0) {
    586                 FD_SET(dp->wfd, &ws);
    587                 if (dp->wfd > maxfd)
    588                     maxfd = dp->wfd;
    589             }
     654            if (dp->active)
     655            {
     656                FD_SET(dp->rfd, &rs);
     657                if (dp->rfd > maxfd)
     658                   maxfd = dp->rfd;
     659                if (dp->pid != REMOTEDVR)
     660                {
     661                   FD_SET(dp->efd, &rs);
     662                   if (dp->efd > maxfd)
     663                      maxfd = dp->efd;
     664                }
     665                if (nFQ(dp->msgq) > 0)
     666                {
     667                   FD_SET(dp->wfd, &ws);
     668                   if (dp->wfd > maxfd)
     669                       maxfd = dp->wfd;
     670                }
     671            }
    590672        }
    591673
     
    597679            Bye();
    598680        }
     681
     682
     683        /* new command from FIFO? */
     684        if (s > 0 && FD_ISSET(fifo.fd, &rs)) {
     685            newFIFO();
     686            s--;
     687        }
    599688
    600689        /* new client? */
     
    642731}
    643732
     733/* Read commands from FIFO and process them. Start/stop drivers accordingly */
     734static void newFIFO(void)
     735{
     736    char line[MAXRBUF], tDriver[MAXRBUF], tConfig[MAXRBUF], tDev[MAXRBUF];
     737    static char *envDev=NULL, *envConfig=NULL;
     738    const char *delm = " ";
     739    char *token, *cp;
     740    DvrInfo *dp = NULL;
     741    int startCmd=0;
     742
     743    if (envDev == NULL)
     744        envDev = (char *) malloc(MAXRBUF* sizeof(char));
     745    if (envConfig == NULL)
     746        envConfig = (char *) malloc(MAXRBUF * sizeof(char));
     747
     748    while ( fgets (line, MAXRBUF, fifo.fs) != NULL)
     749    {
     750        //fprintf(stderr, "FIFO: %s\n", line);
     751        tDev[0] = '\0', tDriver[0] = '\0', tConfig[0] = '\0', envDev[0] = '\0', envConfig[0] = '\0';
     752        cp = strdup(line);
     753
     754        token = strsep(&cp, delm);
     755
     756        if (!strcmp(token, "start") || !strcmp(token, "stop"))
     757        {
     758                if (!strcmp(token, "start"))
     759                    startCmd = 1;
     760
     761                token = strsep(&cp, delm);
     762
     763                if (!token)
     764                    continue;
     765
     766               strncpy(tDriver, token, MAXRBUF);
     767
     768               if (verbose)
     769                fprintf(stderr, "FIFO: Request for %s driver: %s\n", (startCmd == 1) ? "starting" : "stopping", tDriver);
     770
     771               /* Find more name + config */
     772               token = strsep(&cp, delm);
     773
     774               if (token)
     775               {
     776                 /* If config file detected, copy it */
     777                if (strstr(token, ".xml"))                 
     778                    strncpy(tConfig, token, MAXRBUF);
     779                /* Get rid of quotes */
     780                else if (strstr(token, "\"") || strstr(token, "'"))
     781                {
     782                    strncat(tDev, ++token, MAXRBUF);
     783                    while (token = strsep(&cp, delm) )
     784                   {
     785                     strcat(tDev, " ");
     786                     strncat(tDev, token, MAXRBUF);
     787                     if (strstr(token, "\"") || strstr(token, "'"))
     788                     {
     789                         tDev[strlen(tDev)-1] = '\0';
     790                         break;
     791                     }
     792                    }
     793                 }
     794                 else
     795                     strncpy(tDev, token, MAXRBUF);
     796
     797                  /* Find config, if there is any */
     798                  token = strsep(&cp, delm);
     799                  if (token)
     800                  {
     801                      /* Get rid of quotes */
     802                      if (strstr(token, "\"") || strstr(token, "'"))
     803                      {
     804                       strncat(tConfig, ++token, MAXRBUF);
     805                       while (token = strsep(&cp, delm) )
     806                       {
     807                          strcat(tConfig, " ");
     808                          strncat(tConfig, token, MAXRBUF);
     809
     810                          if (strstr(token, "\"") || strstr(token, "'"))
     811                          {
     812                                 tConfig[strlen(tConfig)-1] = '\0';
     813                                 break;
     814                          }
     815                       }
     816                      }
     817                       else
     818                           strncpy(tConfig, token, MAXRBUF);
     819                  }
     820              }
     821
     822               /* Did we find device name? */
     823               if (tDev[0])
     824               {
     825                 snprintf(envDev, MAXRBUF, "INDIDEV=%s", tDev);
     826                 //fprintf(stderr, "With name: %s\n", envDev);
     827                 putenv(envDev);
     828
     829                 //fprintf(stderr, "envionment check INDIDEV: %s\n", getenv("INDIDEV"));
     830               }
     831
     832               /* Did we find config file */
     833               if (tConfig[0])
     834               {
     835                   snprintf(envConfig, MAXRBUF, "INDICONFIG=%s", tConfig);
     836                   //fprintf(stderr, "With config: %s\n", envConfig);
     837                   putenv(envConfig);
     838               }
     839
     840               if (startCmd)
     841               {
     842                   if (verbose)
     843                        fprintf(stderr, "FIFO: Starting driver %s\n", tDriver);
     844                    dp = allocDvr();
     845                    strncpy(dp->name, tDriver, MAXINDIDEVICE);
     846                    strncpy(dp->dev, tDev, MAXINDIDEVICE);
     847                    startDvr (dp);
     848              }
     849               else
     850               {
     851                  for (dp = dvrinfo; dp < &dvrinfo[ndvrinfo]; dp++)
     852                   {
     853                       if (!strcmp(dp->name, tDriver))
     854                       {
     855                           /* If device name is given, check against it before shutting down */
     856                           if (tDev[0] && strcmp(dp->dev, tDev))
     857                               continue;
     858
     859                           if (verbose)
     860                               fprintf(stderr, "FIFO: Shutting down driver: %s\n", tDriver);
     861
     862                           shutdownDvr(dp, 0);
     863
     864                               /* Inform clients that this driver is dead */
     865                               XMLEle *root = addXMLEle (NULL, "delProperty");
     866                               addXMLAtt(root, "device", dp->dev);
     867                               Msg * mp = newMsg();
     868
     869                               q2Clients(NULL, 0, dp->dev, NULL, mp, root);
     870                               if (mp->count > 0)
     871                                   setMsgXMLEle (mp, root);
     872                               else
     873                                   freeMsg (mp);
     874                               delXMLEle (root);
     875
     876                           break;
     877
     878                       }
     879                   }
     880               }
     881         }
     882    }
     883}
     884
    644885/* prepare for new client arriving on lsocket.
    645886 * exit if trouble.
     
    753994                /* echo new* commands back to other clients */
    754995                if (!strncmp (roottag, "new", 3)) {
    755                     if (q2Clients (cp, isblob, dev, name, mp, root) < 0)
     996                    if (q2Clients (cp, isblob, dev, name, mp, root) < 0)
    756997                        shutany++;
    757998                }
     
    7981039                fprintf (stderr, "%s: Driver %s: stdin EOF\n",
    7991040                                                        indi_tstamp(NULL), dp->name);
    800             restartDvr (dp);
     1041            shutdownDvr (dp, 1);
    8011042            return (-1);
    8021043        }
     
    8721113                fprintf (stderr, "%s: Driver %s: XML read: %.*s\n", ts,
    8731114                                                            dp->name, nr, buf);
    874                 restartDvr (dp);
     1115                shutdownDvr (dp, 1);
    8751116                return (-1);
    8761117            }
     
    8991140                fprintf (stderr, "%s: Driver %s: stderr EOF\n",
    9001141                                                        indi_tstamp(NULL), dp->name);
    901             restartDvr (dp);
     1142            shutdownDvr (dp, 1);
    9021143            return (-1);
    9031144        }
     
    9491190/* close down the given driver and restart */
    9501191static void
    951 restartDvr (DvrInfo *dp)
     1192shutdownDvr (DvrInfo *dp, int restart)
    9521193{
    9531194        Msg *mp;
     
    9601201        } else {
    9611202            /* local pipe connection */
    962             kill (dp->pid, SIGKILL);    /* we've insured there are no zombies */
     1203            kill (dp->pid, SIGKILL);    /* we've insured there are no zombies */
    9631204            close (dp->wfd);
    9641205            close (dp->rfd);
     
    9691210        free (dp->sprops);
    9701211        delLilXML (dp->lp);
     1212
     1213        /* ok now to recycle */
     1214        dp->active = 0;
    9711215
    9721216        /* decrement and possibly free any unsent messages for this client */
     
    9761220        delFQ (dp->msgq);
    9771221
    978         fprintf (stderr, "%s: Driver %s: restart #%d\n", indi_tstamp(NULL),
    979                                                     dp->name, ++dp->restarts);
    980         startDvr (dp);
     1222        if (restart)
     1223        {
     1224            fprintf (stderr, "%s: Driver %s: restart #%d\n", indi_tstamp(NULL),
     1225                                                    dp->name, ++dp->restarts);
     1226            startDvr (dp);
     1227        }
     1228
    9811229}
    9821230
     
    12851533                fprintf (stderr, "%s: Driver %s: write: %s\n", indi_tstamp(NULL),
    12861534                                                    dp->name, strerror(errno));
    1287             restartDvr (dp);
     1535            shutdownDvr (dp, 1);
    12881536            return (-1);
    12891537        }
     
    13251573            Property *pp = &cp->props[i];
    13261574            if (!strcmp (pp->dev, dev) &&
    1327                                     (!pp->name[0] || !strcmp(pp->name, name)))
     1575                                    (!pp->name[0] || !strcmp(pp->name, name)))
    13281576                return (0);
    13291577        }
     
    14591707logDMsg (XMLEle *root, const char *dev)
    14601708{
    1461         char stamp[64];
    1462         char logfn[1024];
    1463         const char *ts, *ms;
    1464         FILE *fp;
    1465 
    1466         /* get message, if any */
    1467         ms = findXMLAttValu (root, "message");
    1468         if (!ms[0])
    1469             return;
    1470 
    1471         /* get timestamp now if not provided */
    1472         ts = findXMLAttValu (root, "timestamp");
    1473         if (!ts[0])
    1474         {
    1475             indi_tstamp (stamp);
    1476             ts = stamp;
    1477         }
    1478 
    1479         /* append to log file, name is date portion of time stamp */
    1480         sprintf (logfn, "%s/%.10s.islog", ldir, ts);
    1481         fp = fopen (logfn, "a");
    1482         if (!fp)
    1483             return;     /* oh well */
    1484         fprintf (fp, "%s: %s: %s\n", ts, dev, ms);
    1485         fclose (fp);
     1709        char stamp[64];
     1710        char logfn[1024];
     1711        const char *ts, *ms;
     1712        FILE *fp;
     1713
     1714        /* get message, if any */
     1715        ms = findXMLAttValu (root, "message");
     1716        if (!ms[0])
     1717            return;
     1718
     1719        /* get timestamp now if not provided */
     1720        ts = findXMLAttValu (root, "timestamp");
     1721        if (!ts[0])
     1722        {
     1723            indi_tstamp (stamp);
     1724            ts = stamp;
     1725        }
     1726
     1727        /* append to log file, name is date portion of time stamp */
     1728        sprintf (logfn, "%s/%.10s.islog", ldir, ts);
     1729        fp = fopen (logfn, "a");
     1730        if (!fp)
     1731            return;     /* oh well */
     1732        fprintf (fp, "%s: %s: %s\n", ts, dev, ms);
     1733        fclose (fp);
    14861734}
    14871735
  • BAORadio/libindi/libindi/libindi.pc.cmake

    r490 r501  
    1010Libs: -L@LIB_DESTINATION@ -lindi
    1111Cflags: -I@INCLUDE_INSTALL_DIR@ -@INCLUDE_INSTALL_DIR@/libindi
     12
  • BAORadio/libindi/libindi/libs/indicom.c

    r490 r501  
    2424*/
    2525
    26 /* needed for sincos() in math.h */
    27 #ifndef _GNU_SOURCE
    28 #define _GNU_SOURCE
    29 #endif
    30 #ifdef _WIN32
    31 #define CX _CX
    32 #define CY _CY
    33 #endif
    3426#include <stdlib.h>
    3527#include <math.h>
     
    4032#include <errno.h>
    4133#include <stdarg.h>
    42 
    43 #include <config.h>
     34#include <sys/param.h>
     35
     36//#include <config.h>
    4437
    4538#ifdef HAVE_NOVA_H
    4639#include <libnova.h>
    4740#endif
    48 
    4941
    5042#include "indicom.h"
     
    5244#undef CX
    5345#undef CY
    54 #endif
    55 const char * Direction[] = { "North", "West", "East", "South", "All"};
    56 const char * SolarSystem[] = { "Mercury", "Venus", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"};
    57 
    58 /* make it compile on solaris */
    59 #ifndef M_PI
    60 #define M_PI 3.14159265358979323846264338327950288419716939937510582097494459
    6146#endif
    6247
     
    6752#define PARITY_ODD     2
    6853#endif
     54
     55#define MAXRBUF         2048
     56
     57#include "indidevapi.h"
    6958
    7059void getSexComponents(double value, int *d, int *m, int *s);
     
    387376}
    388377
     378#ifdef BSD
     379// BSD - OSX version
     380int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
     381{
     382       int      t_fd = -1;
     383       int bps;
     384       char msg[80];
     385    int handshake;
     386    struct termios      tty_setting;
     387
     388    // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
     389    // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
     390    // See open(2) ("man 2 open") for details.
     391
     392    t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
     393    if (t_fd == -1)
     394    {
     395        printf("Error opening serial port %s - %s(%d).\n",
     396               device, strerror(errno), errno);
     397        goto error;
     398    }
     399
     400    // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
     401    // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
     402    // processes.
     403    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
     404
     405    if (ioctl(t_fd, TIOCEXCL) == -1)
     406    {
     407        printf("Error setting TIOCEXCL on %s - %s(%d).\n",
     408            device, strerror(errno), errno);
     409        goto error;
     410    }
     411
     412    // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
     413    // See fcntl(2) ("man 2 fcntl") for details.
     414
     415    if (fcntl(t_fd, F_SETFL, 0) == -1)
     416    {
     417        printf("Error clearing O_NONBLOCK %s - %s(%d).\n",
     418            device, strerror(errno), errno);
     419        goto error;
     420    }
     421
     422    // Get the current options and save them so we can restore the default settings later.
     423    if (tcgetattr(t_fd, &tty_setting) == -1)
     424    {
     425        printf("Error getting tty attributes %s - %s(%d).\n",
     426            device, strerror(errno), errno);
     427        goto error;
     428    }
     429
     430    // Set raw input (non-canonical) mode, with reads blocking until either a single character
     431    // has been received or a one second timeout expires.
     432    // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
     433
     434    cfmakeraw(&tty_setting);
     435    tty_setting.c_cc[VMIN] = 1;
     436    tty_setting.c_cc[VTIME] = 10;
     437
     438    // The baud rate, word length, and handshake options can be set as follows:
     439        switch (bit_rate) {
     440                case 0:
     441                        bps = B0;
     442                        break;
     443                case 50:
     444                        bps = B50;
     445                        break;
     446                case 75:
     447                        bps = B75;
     448                        break;
     449                case 110:
     450                        bps = B110;
     451                        break;
     452                case 134:
     453                        bps = B134;
     454                        break;
     455                case 150:
     456                        bps = B150;
     457                        break;
     458                case 200:
     459                        bps = B200;
     460                        break;
     461                case 300:
     462                        bps = B300;
     463                        break;
     464                case 600:
     465                        bps = B600;
     466                        break;
     467                case 1200:
     468                        bps = B1200;
     469                        break;
     470                case 1800:
     471                        bps = B1800;
     472                        break;
     473                case 2400:
     474                        bps = B2400;
     475                        break;
     476                case 4800:
     477                        bps = B4800;
     478                        break;
     479                case 9600:
     480                        bps = B9600;
     481                        break;
     482                case 19200:
     483                        bps = B19200;
     484                        break;
     485                case 38400:
     486                        bps = B38400;
     487                        break;
     488                case 57600:
     489                        bps = B57600;
     490                        break;
     491                case 115200:
     492                        bps = B115200;
     493                        break;
     494                case 230400:
     495                        bps = B230400;
     496                        break;
     497                default:
     498                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate)  0)
     499                                perror(NULL);
     500                        else
     501                                perror(msg);
     502                        return TTY_PARAM_ERROR;
     503        }
     504
     505     cfsetspeed(&tty_setting, bps);             // Set baud rate
     506        /* word size */
     507        switch (word_size) {
     508                case 5:
     509                        tty_setting.c_cflag |= CS5;
     510                        break;
     511                case 6:
     512                        tty_setting.c_cflag |= CS6;
     513                        break;
     514                case 7:
     515                        tty_setting.c_cflag |= CS7;
     516                        break;
     517                case 8:
     518                        tty_setting.c_cflag |= CS8;
     519                        break;
     520                default:
     521
     522                        fprintf( stderr, "Default\n") ;
     523                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size)  0)
     524                                perror(NULL);
     525                        else
     526                                perror(msg);
     527
     528                        return TTY_PARAM_ERROR;
     529        }
     530
     531        /* parity */
     532        switch (parity) {
     533                case PARITY_NONE:
     534                        break;
     535                case PARITY_EVEN:
     536                        tty_setting.c_cflag |= PARENB;
     537                        break;
     538                case PARITY_ODD:
     539                        tty_setting.c_cflag |= PARENB | PARODD;
     540                        break;
     541                default:
     542
     543                        fprintf( stderr, "Default1\n") ;
     544                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity)  0)
     545                                perror(NULL);
     546                        else
     547                                perror(msg);
     548
     549                        return TTY_PARAM_ERROR;
     550        }
     551
     552        /* stop_bits */
     553        switch (stop_bits) {
     554                case 1:
     555                        break;
     556                case 2:
     557                        tty_setting.c_cflag |= CSTOPB;
     558                        break;
     559                default:
     560                        fprintf( stderr, "Default2\n") ;
     561                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits)  0)
     562                                perror(NULL);
     563                        else
     564                                perror(msg);
     565
     566                        return TTY_PARAM_ERROR;
     567        }
     568
     569#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
     570       // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
     571       // other than those specified by POSIX. The driver for the underlying serial hardware
     572       // ultimately determines which baud rates can be used. This ioctl sets both the input
     573       // and output speed.
     574
     575       speed_t speed = 14400; // Set 14400 baud
     576    if (ioctl(fileDescriptor, IOSSIOSPEED, &speed) == -1)
     577    {
     578        printf("Error calling ioctl(..., IOSSIOSPEED, ...) %s - %s(%d).\n",
     579            bsdPath, strerror(errno), errno);
     580    }
     581#endif
     582
     583    // Cause the new options to take effect immediately.
     584    if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
     585    {
     586        printf("Error setting tty attributes %s - %s(%d).\n",
     587            device, strerror(errno), errno);
     588        goto error;
     589    }
     590
     591    // To set the modem handshake lines, use the following ioctls.
     592    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
     593
     594    if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
     595    {
     596        printf("Error asserting DTR %s - %s(%d).\n",
     597            device, strerror(errno), errno);
     598    }
     599
     600    if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
     601    {
     602        printf("Error clearing DTR %s - %s(%d).\n",
     603            device, strerror(errno), errno);
     604    }
     605
     606    handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
     607    if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
     608    // Set the modem lines depending on the bits set in handshake
     609    {
     610        printf("Error setting handshake lines %s - %s(%d).\n",
     611            device, strerror(errno), errno);
     612    }
     613
     614    // To read the state of the modem lines, use the following ioctl.
     615    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
     616
     617    if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
     618    // Store the state of the modem lines in handshake
     619    {
     620        printf("Error getting handshake lines %s - %s(%d).\n",
     621            device, strerror(errno), errno);
     622    }
     623
     624    printf("Handshake lines currently set to %d\n", handshake);
     625
     626#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
     627       unsigned long mics = 1UL;
     628
     629       // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
     630       // dequeue characters received by the hardware. Most applications don't need to set this value: if an
     631       // app reads lines of characters, the app can't do anything until the line termination character has been
     632       // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
     633       // applications.
     634
     635       if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
     636       {
     637               // set latency to 1 microsecond
     638        printf("Error setting read latency %s - %s(%d).\n",
     639            device, strerror(errno), errno);
     640        goto error;
     641       }
     642#endif
     643
     644   *fd = t_fd;
     645  /* return success */
     646  return TTY_OK;
     647
     648    // Failure path
     649error:
     650    if (t_fd != -1)
     651    {
     652        close(t_fd);
     653    }
     654
     655    return TTY_PORT_FAILURE;
     656}
     657#else
    389658int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
    390659{
     
    577846#endif
    578847}
     848// Unix - Linux version
     849
     850#endif
     851
    579852
    580853int tty_disconnect(int fd)
     
    644917   }   
    645918}
     919
     920/* return static string corresponding to the given property or light state */
     921const char *
     922pstateStr (IPState s)
     923{
     924        switch (s) {
     925        case IPS_IDLE:  return ("Idle");
     926        case IPS_OK:    return ("Ok");
     927        case IPS_BUSY:  return ("Busy");
     928        case IPS_ALERT: return ("Alert");
     929        default:
     930            fprintf (stderr, "Impossible IPState %d\n", s);
     931            exit(1);
     932        }
     933}
     934
     935/* crack string into IPState.
     936 * return 0 if ok, else -1
     937 */
     938int
     939crackIPState (const char *str, IPState *ip)
     940{
     941             if (!strcmp (str, "Idle"))  *ip = IPS_IDLE;
     942        else if (!strcmp (str, "Ok"))    *ip = IPS_OK;
     943        else if (!strcmp (str, "Busy"))  *ip = IPS_BUSY;
     944        else if (!strcmp (str, "Alert")) *ip = IPS_ALERT;
     945        else return (-1);
     946        return (0);
     947}
     948
     949/* crack string into ISState.
     950 * return 0 if ok, else -1
     951 */
     952int
     953crackISState (const char *str, ISState *ip)
     954{
     955             if (!strcmp (str, "On"))  *ip = ISS_ON;
     956        else if (!strcmp (str, "Off")) *ip = ISS_OFF;
     957        else return (-1);
     958        return (0);
     959}
     960
     961int
     962crackIPerm (const char *str, IPerm *ip)
     963{
     964             if (!strcmp (str, "rw"))  *ip = IP_RW;
     965        else if (!strcmp (str, "ro")) *ip = IP_RO;
     966        else if (!strcmp (str, "wo")) *ip = IP_WO;
     967        else return (-1);
     968        return (0);
     969}
     970
     971int crackISRule (const char *str, ISRule *ip)
     972{
     973    if (!strcmp (str, "OneOfMany"))  *ip = ISR_1OFMANY;
     974    else if (!strcmp (str, "AtMostOne")) *ip = ISR_ATMOST1;
     975    else if (!strcmp (str, "AnyOfMany")) *ip = ISR_NOFMANY;
     976    else return (-1);
     977  return (0);
     978}
     979
     980/* return static string corresponding to the given switch state */
     981const char *
     982sstateStr (ISState s)
     983{
     984        switch (s) {
     985        case ISS_ON:  return ("On");
     986        case ISS_OFF: return ("Off");
     987        default:
     988            fprintf (stderr, "Impossible ISState %d\n", s);
     989        }
     990}
     991
     992/* return static string corresponding to the given Rule */
     993const char *
     994ruleStr (ISRule r)
     995{
     996        switch (r) {
     997        case ISR_1OFMANY: return ("OneOfMany");
     998        case ISR_ATMOST1: return ("AtMostOne");
     999        case ISR_NOFMANY: return ("AnyOfMany");
     1000        default:
     1001            fprintf (stderr, "Impossible ISRule %d\n", r);
     1002        }
     1003}
     1004
     1005/* return static string corresponding to the given IPerm */
     1006const char *
     1007permStr (IPerm p)
     1008{
     1009        switch (p) {
     1010        case IP_RO: return ("ro");
     1011        case IP_WO: return ("wo");
     1012        case IP_RW: return ("rw");
     1013        default:
     1014            fprintf (stderr, "Impossible IPerm %d\n", p);
     1015        }
     1016}
     1017
     1018/* print the boilerplate comment introducing xml */
     1019void
     1020xmlv1()
     1021{
     1022        printf ("<?xml version='1.0'?>\n");
     1023}
     1024
     1025/* pull out device and name attributes from root.
     1026 * return 0 if ok else -1 with reason in msg[].
     1027 */
     1028int
     1029crackDN (XMLEle *root, char **dev, char **name, char msg[])
     1030{
     1031        XMLAtt *ap;
     1032
     1033        ap = findXMLAtt (root, "device");
     1034        if (!ap) {
     1035            sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
     1036            return (-1);
     1037        }
     1038        *dev = valuXMLAtt(ap);
     1039
     1040        ap = findXMLAtt (root, "name");
     1041        if (!ap) {
     1042            sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
     1043            return (-1);
     1044        }
     1045        *name = valuXMLAtt(ap);
     1046
     1047        return (0);
     1048}
     1049
     1050/* find a member of an IText vector, else NULL */
     1051IText *
     1052IUFindText  (const ITextVectorProperty *tvp, const char *name)
     1053{
     1054        int i;
     1055
     1056        for (i = 0; i < tvp->ntp; i++)
     1057            if (strcmp (tvp->tp[i].name, name) == 0)
     1058                return (&tvp->tp[i]);
     1059        fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
     1060        return (NULL);
     1061}
     1062
     1063/* find a member of an INumber vector, else NULL */
     1064INumber *
     1065IUFindNumber(const INumberVectorProperty *nvp, const char *name)
     1066{
     1067        int i;
     1068
     1069        for (i = 0; i < nvp->nnp; i++)
     1070            if (strcmp (nvp->np[i].name, name) == 0)
     1071                return (&nvp->np[i]);
     1072        fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
     1073        return (NULL);
     1074}
     1075
     1076/* find a member of an ISwitch vector, else NULL */
     1077ISwitch *
     1078IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
     1079{
     1080        int i;
     1081
     1082        for (i = 0; i < svp->nsp; i++)
     1083            if (strcmp (svp->sp[i].name, name) == 0)
     1084                return (&svp->sp[i]);
     1085        fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
     1086        return (NULL);
     1087}
     1088
     1089/* find a member of an ILight vector, else NULL */
     1090ILight *
     1091IUFindLight(const ILightVectorProperty *lvp, const char *name)
     1092{
     1093        int i;
     1094
     1095        for (i = 0; i < lvp->nlp; i++)
     1096            if (strcmp (lvp->lp[i].name, name) == 0)
     1097                return (&lvp->lp[i]);
     1098        fprintf(stderr,"No ILight '%s' in %s.%s\n",name,lvp->device,lvp->name);
     1099        return (NULL);
     1100}
     1101
     1102/* find a member of an IBLOB vector, else NULL */
     1103IBLOB *
     1104IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name)
     1105{
     1106        int i;
     1107
     1108        for (i = 0; i < bvp->nbp; i++)
     1109            if (strcmp (bvp->bp[i].name, name) == 0)
     1110                return (&bvp->bp[i]);
     1111        fprintf(stderr,"No IBLOB '%s' in %s.%s\n",name,bvp->device,bvp->name);
     1112        return (NULL);
     1113}
     1114
     1115/* find an ON member of an ISwitch vector, else NULL.
     1116 * N.B. user must make sense of result with ISRule in mind.
     1117 */
     1118ISwitch *
     1119IUFindOnSwitch(const ISwitchVectorProperty *svp)
     1120{
     1121        int i;
     1122
     1123        for (i = 0; i < svp->nsp; i++)
     1124            if (svp->sp[i].s == ISS_ON)
     1125                return (&svp->sp[i]);
     1126        /*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
     1127        return (NULL);
     1128}
     1129
     1130/* Set all switches to off */
     1131void
     1132IUResetSwitch(ISwitchVectorProperty *svp)
     1133{
     1134  int i;
     1135
     1136  for (i = 0; i < svp->nsp; i++)
     1137    svp->sp[i].s = ISS_OFF;
     1138}
     1139
     1140/* save malloced copy of newtext in tp->text, reusing if not first time */
     1141void
     1142IUSaveText (IText *tp, const char *newtext)
     1143{
     1144        /* seed for realloc */
     1145        if (tp->text == NULL)
     1146            tp->text = malloc (1);
     1147
     1148        /* copy in fresh string */
     1149        tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
     1150}
  • BAORadio/libindi/libindi/libs/indicom.h

    r490 r501  
    4848#define ERRMSG_SIZE 1024
    4949#define INDI_DEBUG
    50 
    5150
    5251extern const char * Direction[];
  • BAORadio/libindi/libindi/libs/lilxml.h

    r490 r501  
    248248*   N.B. s must be at least as large as that reported by sprlXMLEle()+1.
    249249*   N.B. set level = 0 on first call.
    250 *   \return return length of resulting string (sans trailing \0)
     250*   \return return length of resulting string (sans trailing @\0@)
    251251*/
    252252extern int sprXMLEle (char *s, XMLEle *ep, int level);
    253253
    254 /** \brief return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing \0).
     254/** \brief return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing @\0@).
    255255*   N.B. set level = 0 on first call.
    256256*/
Note: See TracChangeset for help on using the changeset viewer.