Index: /BAORadio/.directory
===================================================================
--- /BAORadio/.directory	(revision 501)
+++ /BAORadio/.directory	(revision 501)
@@ -0,0 +1,5 @@
+[Dolphin]
+Timestamp=2010,10,3,23,6,16
+
+[Settings]
+ShowDotFiles=true
Index: /BAORadio/libindi/libindi/BAOTest/baocontrol.h
===================================================================
--- /BAORadio/libindi/libindi/BAOTest/baocontrol.h	(revision 501)
+++ /BAORadio/libindi/libindi/BAOTest/baocontrol.h	(revision 501)
@@ -0,0 +1,93 @@
+#include <iostream>
+#include <string.h>
+#include <sstream>
+#include "ClientSocket.h"
+#include "SocketException.h"
+#include <stdio.h>
+#include <pthread.h>
+#include <X11/Xlib.h>
+#include "filetools.h"
+#include "astro.h"
+#include "math.h"
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#define red "\033[0;31m"
+#define blue "\033[0;34m"
+#define green "\033[0;32m"
+#define black "\033[0;30m"
+
+#define MAXLOG 1000
+#define MAXOBJETS 100
+#define MAXANTENNES 100
+
+using namespace std;
+
+
+struct DefAntenne
+{
+    unsigned char ip;
+
+    char ok;
+};
+
+struct DefObjets
+{
+    double JJ;
+    double Duree;
+    char ad[10];
+    char de[10];
+    bool exec;
+};
+
+
+char Latitude[80];
+char Longitude[80];
+char Serveur[80];
+
+std::string logs[MAXLOG];
+
+std::stringstream os;
+
+int Port=0;
+int delaitransit=0;
+int delaitracking=0;
+int lognum=0;
+int numAntenne=0;
+int numobjets=0;
+int runnum=1;
+
+struct DefAntenne Antennes[MAXANTENNES];
+struct DefObjets objets[MAXOBJETS];
+
+bool NoExit=true;
+bool Transit=false;
+bool run=false;
+bool exitrun=false;
+
+ClientSocket *client_socket;
+Astro *astro;
+
+Display * d;
+Window w;
+GC noir, vert, rouge, gris;
+
+
+void initialiserFenetre();
+void Dessiner();
+void rouler(char* reponse);
+void LireReponse();
+void *my_thread_process (void * arg);
+bool Decomposition(std::string chaine, char type, float *a1, float *a2, float *a3);
+bool DecompositionCommande(std::string chaine, std::string commande, std::string *chaine1, std::string *chaine2);
+bool EncoyerCoordGeographiques();
+bool Connect(bool connect);
+bool Park();
+bool Abort();
+bool Goto(std::string ar, std::string dec, bool Transit);
+bool LectureFichierMouvements(char * fileName);
+bool Run(std::string fichier);
+void DecodageFonction(std::string chaine);
+bool ChargementParametres(); 
Index: /BAORadio/libindi/libindi/BAOTest/simple_server_main.cpp
===================================================================
--- /BAORadio/libindi/libindi/BAOTest/simple_server_main.cpp	(revision 500)
+++ /BAORadio/libindi/libindi/BAOTest/simple_server_main.cpp	(revision 501)
@@ -10,5 +10,5 @@
     {
       // Create the socket
-      ServerSocket server ( 8000 );
+      ServerSocket server ( 7624 );
 
       while ( true )
Index: /BAORadio/libindi/libindi/CMakeLists.txt
===================================================================
--- /BAORadio/libindi/libindi/CMakeLists.txt	(revision 500)
+++ /BAORadio/libindi/libindi/CMakeLists.txt	(revision 501)
@@ -1,12 +1,15 @@
 cmake_minimum_required(VERSION 2.4.7)
 
+ if(COMMAND cmake_policy)
+      cmake_policy(SET CMP0003 NEW)
+    endif(COMMAND cmake_policy)
+
+
 
 ##################  INDI version  ################################
-set(INDI_VERSION "0.6")
 set(INDI_SOVERSION "0")
-
 set(CMAKE_INDI_VERSION_MAJOR 0)
-set(CMAKE_INDI_VERSION_MINOR 6)
-set(CMAKE_INDI_VERSION_RELEASE 1)
+set(CMAKE_INDI_VERSION_MINOR 7)
+set(CMAKE_INDI_VERSION_RELEASE 0)
 set(CMAKE_INDI_VERSION_STRING "${CMAKE_INDI_VERSION_MAJOR}.${CMAKE_INDI_VERSION_MINOR}.${CMAKE_INDI_VERSION_RELEASE}")
 
@@ -51,5 +54,4 @@
 macro_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.")
 
-
 macro_optional_find_package(Nova)
 macro_bool_to_01(NOVA_FOUND HAVE_NOVA_H)
@@ -59,6 +61,4 @@
 check_include_files(termios.h TERMIOS_FOUND)
 macro_bool_to_01(TERMIOS_FOUND HAVE_TERMIOS_H)
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h )
 
 include_directories( ${CMAKE_CURRENT_BINARY_DIR})
@@ -95,8 +95,20 @@
 
 set (indimain_SRCS
+        ${CMAKE_SOURCE_DIR}/indidriver.c
 	${CMAKE_SOURCE_DIR}/indidrivermain.c
 	${CMAKE_SOURCE_DIR}/eventloop.c
     )
 
+set (indibase_SRCS
+        ${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.cpp
+        ${CMAKE_SOURCE_DIR}/libs/indibase/baseclient.cpp
+    )
+
+set (indidefaultdevice_SRCS
+        ${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.cpp
+        ${CMAKE_SOURCE_DIR}/libs/indibase/defaultdriver.cpp
+    )
+
+
 ######################################
 ########### INDI SERVER ##############
@@ -115,9 +127,4 @@
 install(TARGETS indiserver RUNTIME DESTINATION bin )
 
-######################################
-######## INDI Static Library #########
-######################################
-add_library(indidriver STATIC ${indimain_SRCS})
-install(TARGETS indidriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
 
 ######################################
@@ -138,5 +145,25 @@
 
 install(TARGETS indi LIBRARY DESTINATION lib${LIB_POSTFIX})
-set_target_properties(indi PROPERTIES VERSION ${INDI_VERSION} SOVERSION ${INDI_SOVERSION})
+set_target_properties(indi PROPERTIES VERSION ${CMAKE_INDI_VERSION_STRING} SOVERSION ${INDI_SOVERSION})
+
+
+######################################
+######## INDI Static Library #########
+######################################
+add_library(indidriver STATIC ${indimain_SRCS})
+install(TARGETS indidriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
+
+##############################################
+######## INDI Default Driver Library #########
+##############################################
+add_library(indidefaultdriver STATIC ${indimain_SRCS} ${indidefaultdevice_SRCS})
+install(TARGETS indidefaultdriver ARCHIVE DESTINATION lib${LIB_POSTFIX})
+
+##############################################
+######## INDI Client Library #########
+##############################################
+add_library(indiclient STATIC ${indibase_SRCS})
+target_link_libraries(indiclient indi)
+install(TARGETS indiclient ARCHIVE DESTINATION lib${LIB_POSTFIX})
 
 #####################################
@@ -202,4 +229,5 @@
 target_link_libraries(indi_celestron_gps m )
 
+
 if (NOVA_FOUND)
   target_link_libraries(indi_celestron_gps ${NOVA_LIBRARIES})
@@ -601,4 +629,19 @@
 endif (NOVA_FOUND)
 
+########### Tutorial four ##############
+set(tutorialfour_SRCS
+        ${indimain_SRCS}
+        ${CMAKE_SOURCE_DIR}/examples/tutorial_four.cpp
+   )
+
+add_executable(tutorial_four ${tutorialfour_SRCS} ${liblilxml_SRCS} ${libindicom_SRCS})
+
+target_link_libraries(tutorial_four indidefaultdriver indiclient m z pthread)
+
+if (NOVA_FOUND)
+  target_link_libraries(tutorial_four ${NOVA_LIBRARIES})
+endif (NOVA_FOUND)
+
+
 ########### Tutorial dome ##############
 set(tutorialdome_SRCS
@@ -633,6 +676,8 @@
 install( FILES drivers.xml DESTINATION ${DATA_INSTALL_DIR})
 
-install( FILES indiapi.h indidevapi.h base64.h eventloop.h ${CMAKE_SOURCE_DIR}/libs/lilxml.h
- ${CMAKE_SOURCE_DIR}/libs/indicom.h DESTINATION ${INCLUDE_INSTALL_DIR}/libindi COMPONENT Devel)
+install( FILES indiapi.h indidevapi.h base64.h eventloop.h indidriver.h ${CMAKE_SOURCE_DIR}/libs/lilxml.h ${CMAKE_SOURCE_DIR}/libs/indibase/indibase.h
+${CMAKE_SOURCE_DIR}/libs/indibase/basedriver.h  ${CMAKE_SOURCE_DIR}/libs/indibase/defaultdriver.h
+${CMAKE_SOURCE_DIR}/libs/indibase/baseclient.h ${CMAKE_SOURCE_DIR}/libs/indicom.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/libindi COMPONENT Devel)
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libindi.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libindi.pc @ONLY)
Index: /BAORadio/libindi/libindi/ChangeLog
===================================================================
--- /BAORadio/libindi/libindi/ChangeLog	(revision 500)
+++ /BAORadio/libindi/libindi/ChangeLog	(revision 501)
@@ -1,2 +1,20 @@
+From 0.6.2 to 0.7.0
+
+      # Dynamic renaming of drivers upon run time.
+      # Standard helper API to create and utilize INDI clients.
+      # Ability to load driver properties from an external XML file.
+      # Ability to write/read XML configuration files for driver values to be loaded at run time.
+      # Facilitating debugging and simulation of drivers.
+      # New C++ framework to facilitate the development of new INDI drivers.
+      # Several bug fixes for current drivers and framework. 
+
+From 0.6.1 to 0.6.2
+
+	# Build related updates.
+
+From 0.6 to 0.6.1
+
+	# Updating drivers.xml to comply to new XML structure for group and devices metadata descriptions.
+
 From 0.5 to 0.6
 
Index: /BAORadio/libindi/libindi/Doxyfile
===================================================================
--- /BAORadio/libindi/libindi/Doxyfile	(revision 500)
+++ /BAORadio/libindi/libindi/Doxyfile	(revision 501)
@@ -1,7 +1,8 @@
-# Doxyfile 1.4.1-KDevelop
+# Doxyfile 1.7.1
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "Instrument Neutral Distributed Interface INDI"
 PROJECT_NUMBER         = 0.7
@@ -9,24 +10,33 @@
 CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
-USE_WINDOWS_ENCODING   = NO
 BRIEF_MEMBER_DESC      = YES
 REPEAT_BRIEF           = YES
-ABBREVIATE_BRIEF       = 
+ABBREVIATE_BRIEF       =
 ALWAYS_DETAILED_SEC    = NO
 INLINE_INHERITED_MEMB  = NO
 FULL_PATH_NAMES        = NO
-STRIP_FROM_PATH        = 
-STRIP_FROM_INC_PATH    = 
+STRIP_FROM_PATH        =
+STRIP_FROM_INC_PATH    =
 SHORT_NAMES            = NO
 JAVADOC_AUTOBRIEF      = NO
+QT_AUTOBRIEF           = NO
 MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP         = NO
 INHERIT_DOCS           = YES
-DISTRIBUTE_GROUP_DOC   = NO
+SEPARATE_MEMBER_PAGES  = NO
 TAB_SIZE               = 8
-ALIASES                = 
+ALIASES                =
 OPTIMIZE_OUTPUT_FOR_C  = NO
 OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+EXTENSION_MAPPING      =
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+IDL_PROPERTY_SUPPORT   = YES
+DISTRIBUTE_GROUP_DOC   = NO
 SUBGROUPING            = YES
+TYPEDEF_HIDES_STRUCT   = NO
+SYMBOL_CACHE_SIZE      = 0
 #---------------------------------------------------------------------------
 # Build related configuration options
@@ -37,4 +47,5 @@
 EXTRACT_LOCAL_CLASSES  = YES
 EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
 HIDE_UNDOC_MEMBERS     = YES
 HIDE_UNDOC_CLASSES     = YES
@@ -45,7 +56,10 @@
 HIDE_SCOPE_NAMES       = NO
 SHOW_INCLUDE_FILES     = YES
+FORCE_LOCAL_INCLUDES   = NO
 INLINE_INFO            = YES
 SORT_MEMBER_DOCS       = YES
 SORT_BRIEF_DOCS        = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES       = NO
 SORT_BY_SCOPE_NAME     = NO
 GENERATE_TODOLIST      = YES
@@ -53,9 +67,12 @@
 GENERATE_BUGLIST       = YES
 GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS       = 
+ENABLED_SECTIONS       =
 MAX_INITIALIZER_LINES  = 30
 SHOW_USED_FILES        = YES
 SHOW_DIRECTORIES       = YES
-FILE_VERSION_FILTER    = 
+SHOW_FILES             = YES
+SHOW_NAMESPACES        = YES
+FILE_VERSION_FILTER    =
+LAYOUT_FILE            =
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
@@ -67,9 +84,10 @@
 WARN_NO_PARAMDOC       = NO
 WARN_FORMAT            = "$file:$line: $text"
-WARN_LOGFILE           = 
+WARN_LOGFILE           =
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
-INPUT                  = /home/jasem/Projects/trunk/libindi
+INPUT                  = /home/jasem/Projects/indi/trunk/libindi
+INPUT_ENCODING         = UTF-8
 FILE_PATTERNS          = *.c \
                          *.cc \
@@ -103,19 +121,20 @@
                          *.dox
 RECURSIVE              = YES
-EXCLUDE                = /home/jasem/Projects/trunk/libindi/drivers \
-                         /home/jasem/Projects/trunk/libindi/tools \
-                         /home/jasem/Projects/trunk/libindi/libs/webcam \
-                         /home/jasem/Projects/trunk/libindi/libs/base64.c \
-                         /home/jasem/Projects/trunk/libindi/libs/fq.c \
-                         /home/jasem/Projects/trunk/libindi/indidrivermain.c \
-                         /home/jasem/Projects/trunk/libindi/indiserver.c
+EXCLUDE                = /home/jasem/Projects/indi/trunk/libindi/drivers \
+                         /home/jasem/Projects/indi/trunk/libindi/tools \
+                         /home/jasem/Projects/indi/trunk/libindi/libs/webcam \
+                         /home/jasem/Projects/indi/trunk/libindi/libs/base64.c \
+                         /home/jasem/Projects/indi/trunk/libindi/libs/fq.c \
+                         /home/jasem/Projects/indi/trunk/libindi/indidrivermain.c \
+                         /home/jasem/Projects/indi/trunk/libindi/indiserver.c
 EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = 
-EXAMPLE_PATH           = 
+EXCLUDE_PATTERNS       =
+EXCLUDE_SYMBOLS        =
+EXAMPLE_PATH           =
 EXAMPLE_PATTERNS       = *
 EXAMPLE_RECURSIVE      = NO
-IMAGE_PATH             = 
-INPUT_FILTER           = 
-FILTER_PATTERNS        = 
+IMAGE_PATH             =
+INPUT_FILTER           =
+FILTER_PATTERNS        =
 FILTER_SOURCE_FILES    = NO
 #---------------------------------------------------------------------------
@@ -127,4 +146,6 @@
 REFERENCED_BY_RELATION = NO
 REFERENCES_RELATION    = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
 VERBATIM_HEADERS       = NO
 #---------------------------------------------------------------------------
@@ -133,5 +154,5 @@
 ALPHABETICAL_INDEX     = YES
 COLS_IN_ALPHA_INDEX    = 5
-IGNORE_PREFIX          = 
+IGNORE_PREFIX          =
 #---------------------------------------------------------------------------
 # configuration options related to the HTML output
@@ -140,18 +161,45 @@
 HTML_OUTPUT            = doc
 HTML_FILE_EXTENSION    = .html
-HTML_HEADER            = 
-HTML_FOOTER            = 
-HTML_STYLESHEET        = 
+HTML_HEADER            =
+HTML_FOOTER            =
+HTML_STYLESHEET        =
+HTML_COLORSTYLE_HUE    = 220
+HTML_COLORSTYLE_SAT    = 100
+HTML_COLORSTYLE_GAMMA  = 80
+HTML_TIMESTAMP         = YES
 HTML_ALIGN_MEMBERS     = YES
+HTML_DYNAMIC_SECTIONS  = NO
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME  = Publisher
 GENERATE_HTMLHELP      = NO
-CHM_FILE               = 
-HHC_LOCATION           = 
+CHM_FILE               =
+HHC_LOCATION           =
 GENERATE_CHI           = NO
+CHM_INDEX_ENCODING     =
 BINARY_TOC             = NO
 TOC_EXPAND             = NO
+GENERATE_QHP           = NO
+QCH_FILE               =
+QHP_NAMESPACE          = org.doxygen.Project
+QHP_VIRTUAL_FOLDER     = doc
+QHP_CUST_FILTER_NAME   =
+QHP_CUST_FILTER_ATTRS  =
+QHP_SECT_FILTER_ATTRS  =
+QHG_LOCATION           =
+GENERATE_ECLIPSEHELP   = NO
+ECLIPSE_DOC_ID         = org.doxygen.Project
 DISABLE_INDEX          = NO
 ENUM_VALUES_PER_LINE   = 4
 GENERATE_TREEVIEW      = NO
+USE_INLINE_TREES       = NO
 TREEVIEW_WIDTH         = 250
+EXT_LINKS_IN_WINDOW    = NO
+FORMULA_FONTSIZE       = 10
+FORMULA_TRANSPARENT    = YES
+SEARCHENGINE           = NO
+SERVER_BASED_SEARCH    = NO
 #---------------------------------------------------------------------------
 # configuration options related to the LaTeX output
@@ -163,10 +211,11 @@
 COMPACT_LATEX          = NO
 PAPER_TYPE             = a4wide
-EXTRA_PACKAGES         = 
-LATEX_HEADER           = 
+EXTRA_PACKAGES         =
+LATEX_HEADER           =
 PDF_HYPERLINKS         = NO
 USE_PDFLATEX           = NO
 LATEX_BATCHMODE        = NO
 LATEX_HIDE_INDICES     = NO
+LATEX_SOURCE_CODE      = NO
 #---------------------------------------------------------------------------
 # configuration options related to the RTF output
@@ -176,6 +225,6 @@
 COMPACT_RTF            = NO
 RTF_HYPERLINKS         = NO
-RTF_STYLESHEET_FILE    = 
-RTF_EXTENSIONS_FILE    = 
+RTF_STYLESHEET_FILE    =
+RTF_EXTENSIONS_FILE    =
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
@@ -190,6 +239,6 @@
 GENERATE_XML           = NO
 XML_OUTPUT             = xml
-XML_SCHEMA             = 
-XML_DTD                = 
+XML_SCHEMA             =
+XML_DTD                =
 XML_PROGRAMLISTING     = YES
 #---------------------------------------------------------------------------
@@ -203,7 +252,7 @@
 PERLMOD_LATEX          = NO
 PERLMOD_PRETTY         = YES
-PERLMOD_MAKEVAR_PREFIX = 
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 ENABLE_PREPROCESSING   = YES
@@ -211,23 +260,28 @@
 EXPAND_ONLY_PREDEF     = NO
 SEARCH_INCLUDES        = YES
-INCLUDE_PATH           = 
-INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = 
-EXPAND_AS_DEFINED      = 
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  =
+PREDEFINED             =
+EXPAND_AS_DEFINED      =
 SKIP_FUNCTION_MACROS   = YES
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-TAGFILES               = 
-GENERATE_TAGFILE       = 
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES               =
+GENERATE_TAGFILE       =
 ALLEXTERNALS           = NO
 EXTERNAL_GROUPS        = YES
 PERL_PATH              = /usr/bin/perl
 #---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
+# Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            =
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = NO
+DOT_NUM_THREADS        = 0
+DOT_FONTNAME           = FreeSans.ttf
+DOT_FONTSIZE           = 10
+DOT_FONTPATH           =
 CLASS_GRAPH            = YES
 COLLABORATION_GRAPH    = YES
@@ -238,11 +292,11 @@
 INCLUDED_BY_GRAPH      = YES
 CALL_GRAPH             = NO
+CALLER_GRAPH           = NO
 GRAPHICAL_HIERARCHY    = YES
 DIRECTORY_GRAPH        = YES
 DOT_IMAGE_FORMAT       = png
-DOT_PATH               = 
-DOTFILE_DIRS           = 
-MAX_DOT_GRAPH_WIDTH    = 1024
-MAX_DOT_GRAPH_HEIGHT   = 1024
+DOT_PATH               =
+DOTFILE_DIRS           =
+DOT_GRAPH_MAX_NODES    = 50
 MAX_DOT_GRAPH_DEPTH    = 1000
 DOT_TRANSPARENT        = NO
@@ -250,6 +304,2 @@
 GENERATE_LEGEND        = YES
 DOT_CLEANUP            = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-SEARCHENGINE           = NO
Index: /BAORadio/libindi/libindi/INSTALL
===================================================================
--- /BAORadio/libindi/libindi/INSTALL	(revision 500)
+++ /BAORadio/libindi/libindi/INSTALL	(revision 501)
@@ -1,3 +1,3 @@
-INDI Library Setup 0.6.1
+INDI Library Setup 0.7.0
 ========================
 
Index: /BAORadio/libindi/libindi/NEWS
===================================================================
--- /BAORadio/libindi/libindi/NEWS	(revision 500)
+++ /BAORadio/libindi/libindi/NEWS	(revision 501)
@@ -3,4 +3,4 @@
 -------------------------------------------------------------------------
 
-For the latest news on INDI, refer to INDI's website @ http://indi.sf.net
+For the latest news on INDI, refer to INDI's website @ http://www.indilib.org
 
Index: /BAORadio/libindi/libindi/README
===================================================================
--- /BAORadio/libindi/libindi/README	(revision 500)
+++ /BAORadio/libindi/libindi/README	(revision 501)
@@ -1,2 +1,5 @@
+libindi v0.6.2
+==============
+
 The code here demonstrates the use of INDI, an Instrument-Neutral Device
 Interface protocol. See http://www.clearskyinstitute.com/INDI/INDI.pdf.
Index: /BAORadio/libindi/libindi/cmake_modules/FindINDI.cmake
===================================================================
--- /BAORadio/libindi/libindi/cmake_modules/FindINDI.cmake	(revision 500)
+++ /BAORadio/libindi/libindi/cmake_modules/FindINDI.cmake	(revision 501)
@@ -5,6 +5,8 @@
 #  INDI_INCLUDE_DIR - the INDI include directory
 #  INDI_LIBRARIES - Link these to use INDI
+#  INDI_DEVICE_LIBRARY - The indi default device library
+#  INDI_DATA_DIR - INDI shared data dir.
 
-# Copyright (c) 2006, Jasem Mutlaq <mutlaqja@ikarustech.com>
+# Copyright (c) 2010, Jasem Mutlaq <mutlaqja@ikarustech.com>
 # Based on FindLibfacile by Carsten Niehaus, <cniehaus@gmx.de>
 #
@@ -27,4 +29,12 @@
   )
 
+ find_path(INDI_DATA_DIR drivers.xml
+    PATH_SUFFIXES indi
+    /usr
+    /usr/local
+    /opt
+    ${GNUWIN32_DIR}/share
+  )
+
   find_library(INDI_DRIVER_LIBRARIES NAMES indidriver
     PATHS
@@ -32,4 +42,11 @@
     ${GNUWIN32_DIR}/lib
   )
+
+  find_library(INDI_DEVICE_LIBRARIES NAMES indidefaultdevice
+    PATHS
+    ${_obLinkDir}
+    ${GNUWIN32_DIR}/lib
+  )
+
 
   find_library(INDI_LIBRARIES NAMES indi
@@ -52,9 +69,9 @@
   else (INDI_FOUND)
     if (INDI_FIND_REQUIRED)
-      message(FATAL_ERROR "indi-devel not found. Cannot compile INDI drivers. Please install indi-devel and try again. http://indi.sf.net")
+      message(FATAL_ERROR "indi-devel not found. Cannot compile INDI drivers. Please install indi-devel and try again. http://www.indilib.org")
     endif (INDI_FIND_REQUIRED)
   endif (INDI_FOUND)
 
-  mark_as_advanced(INDI_INCLUDE_DIR INDI_LIBRARIES INDI_DRIVER_LIBRARIES)
+  mark_as_advanced(INDI_INCLUDE_DIR INDI_LIBRARIES INDI_DRIVER_LIBRARIES INDI_DEVICE_LIBRARIES INDI_DATA_DIR)
 
 endif (INDI_INCLUDE_DIR AND INDI_LIBRARIES AND INDI_DRIVER_LIBRARIES)
Index: /BAORadio/libindi/libindi/drivers/filter_wheel/trutech_wheel.c
===================================================================
--- /BAORadio/libindi/libindi/drivers/filter_wheel/trutech_wheel.c	(revision 500)
+++ /BAORadio/libindi/libindi/drivers/filter_wheel/trutech_wheel.c	(revision 501)
@@ -70,4 +70,7 @@
 #define FIRST_FILTER			1
 
+#define DEBUG_ON                        0
+#define SIMULATION_ON                   0
+
 
 /*INDI controls */
@@ -166,5 +169,5 @@
 		unsigned char chksum = COMM_INIT + type + COMM_FILL;
 		/*char filter_command[5] = { COMM_PRE, COMM_INIT, type, COMM_FILL, chksum };*/
-		char filter_command[CMD_SIZE];
+                unsigned char filter_command[CMD_SIZE];
 		snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
 
@@ -172,6 +175,14 @@
 			return;
 
-		err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
-		
+                if (!SIMULATION_ON)
+                    err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
+
+
+                if (DEBUG_ON)
+                {
+                    IDLog("Home Search Command (int): #%d#%d#%d#%d#%d#\n",COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
+                    IDLog("Home Search Command (char): #%c#%c#%c#%c#%c#\n",COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
+                }
+
 		/* Send Home Command */
 		if (err != TTY_OK)
@@ -247,10 +258,9 @@
 			targetFilter = values[0];
 			int nbytes=0;
-			char type = 0x01;
-			char chksum = COMM_INIT + type + (char) targetFilter;
+                        unsigned char type = 0x01;
+                        unsigned char chksum = COMM_INIT + type + (unsigned char) targetFilter;
 			/*char filter_command[5] = { COMM_PRE, COMM_INIT, type, targetFilter, chksum };*/
-			char filter_command[CMD_SIZE];
-
-			snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
+                        unsigned char filter_command[CMD_SIZE];
+
 
 			if (targetFilter < FilterPositionN[0].min || targetFilter > FilterPositionN[0].max)
@@ -262,5 +272,16 @@
 
 			IUUpdateNumber(&FilterPositionNP, values, names, n);
-			err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
+
+                        snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, targetFilter, chksum);
+
+                        if (DEBUG_ON)
+                        {
+                            IDLog("Filter Position Command (int): #%d#%d#%d#%d#%d#\n",COMM_PRE, COMM_INIT, type, targetFilter, chksum);
+                            IDLog("Filter Position Command (char): #%c#%c#%c#%c#%c#\n",COMM_PRE, COMM_INIT, type, targetFilter, chksum);
+                        }
+
+                        if (!SIMULATION_ON)
+                            err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
+
 
 			FilterPositionNP.s = IPS_OK;
@@ -385,4 +406,11 @@
 	{
 		case ISS_ON:
+                        if (SIMULATION_ON)
+                        {
+                            PowerSP.s = IPS_OK;
+                            IDSetSwitch(&PowerSP, "Simulated Filter Wheel is online.");
+                            return;
+                        }
+
 			if ( (err = tty_connect(PortT[0].text, 9600, 8, 0, 1, &fd)) != TTY_OK)
 			{
@@ -394,4 +422,5 @@
 			}
 
+
 			PowerSP.s = IPS_OK;
 			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.");
@@ -399,4 +428,11 @@
 		
 		case ISS_OFF:
+                        if (SIMULATION_ON)
+                        {
+                          PowerSP.s = IPS_OK;
+                          IDSetSwitch(&PowerSP, "Simulated Filter Wheel is offline.");
+                          return;
+                        }
+
 			if ( (err = tty_disconnect(fd)) != TTY_OK)
 			{
Index: /BAORadio/libindi/libindi/drivers/telescope/BAO.cpp
===================================================================
--- /BAORadio/libindi/libindi/drivers/telescope/BAO.cpp	(revision 500)
+++ /BAORadio/libindi/libindi/drivers/telescope/BAO.cpp	(revision 501)
@@ -1,191 +1,191 @@
-  #if 0
-  
-  #############################
-  ##
-  ## BAORadio Indi driver
-  ## Franck RICHARD
-  ## Mai 2010
-  ##
-  #############################
-  #endif
-  
-  #include <stdio.h>
-  #include <stdlib.h>
-  #include <string.h>
-  #include <stdarg.h>
-  #include <math.h>
-  #include <unistd.h>
-  #include <time.h>
-  #include <memory>
-  #include <pthread.h>
-  #include <iostream>
-  #include <time.h>
-  #include <unistd.h>
-  #include <sys/time.h>
-  
-  #include <config.h>
-  
-  #include "indicom.h"
-  
-  #include "Socket.h"
-  
-  #include "BAO.h"
-  
-  using namespace std;
-  
-  auto_ptr<BAO> telescope(0);
-  
-  const int POLLMS = 1;				// Period of update, 1 ms.
-  
-  const char *mydev = "BAO";			// Name of our device.
-  
-  const char *BASIC_GROUP    = "Main Control";		// Main Group
-  const char *OPTIONS_GROUP  = "Options";			// Options Group
-  
-  /* Handy Macros */
-  //#define currentRA	EquatorialCoordsRN[0].value
-  //#define currentDEC	EquatorialCoordsRN[1].value
-  #define targetRA	EquatorialCoordsWN[0].value
-  #define targetDEC	EquatorialCoordsWN[1].value
-  
-  
-  static void ISPoll(void *);
-  
-  static void retry_connection(void *);
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void *pThreadSocket (void * arg)
-  {
+#if 0
+
+#############################
+##
+## BAORadio Indi driver
+## Franck RICHARD
+## Mai 2010
+##
+#############################
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <memory>
+#include <pthread.h>
+#include <iostream>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <config.h>
+
+#include "indicom.h"
+
+#include "Socket.h"
+
+#include "BAO.h"
+
+using namespace std;
+
+auto_ptr<BAO> telescope(0);
+
+const int POLLMS = 1;				// Period of update, 1 ms.
+
+const char *mydev = "BAO";			// Name of our device.
+
+const char *BASIC_GROUP    = "Main Control";		// Main Group
+const char *OPTIONS_GROUP  = "Options";			// Options Group
+
+/* Handy Macros */
+//#define currentRA	EquatorialCoordsRN[0].value
+//#define currentDEC	EquatorialCoordsRN[1].value
+#define targetRA	EquatorialCoordsWN[0].value
+#define targetDEC	EquatorialCoordsWN[1].value
+
+
+static void ISPoll(void *);
+
+static void retry_connection(void *);
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void *pThreadSocket (void * arg)
+{
     try
     {
-      int pos = SocketsNumber;
-      
-      // Trouver Ã©ventuellement un emplacement disponible dans l'intervalle [1..SocketsNumber]
-      
-      /*
-      for (int i=1; i<SocketsNumber; i++)
-      {
-	if (!Sockets[i].Connected)
-	{
-	  pos = i;
-	  break;
-    }
-    }*/
-      
-      server.accept ( Sockets[pos].new_sock );
-      
-      Sockets[pos].IP=server.recupip(Sockets[pos].new_sock);
-      
-      Sockets[pos].Connected=true;
-      
-      if (pos == SocketsNumber ) SocketsNumber++;
-      
-      InitThreadOK=true;
+        int pos = SocketsNumber;
+
+        // Trouver Ã©ventuellement un emplacement disponible dans l'intervalle [1..SocketsNumber]
+
+        /*
+        for (int i=1; i<SocketsNumber; i++)
+        {
+        if (!Sockets[i].Connected)
+        {
+        pos = i;
+        break;
+        }
+        }*/
+
+        server.accept ( Sockets[pos].new_sock );
+
+        Sockets[pos].IP=server.recupip(Sockets[pos].new_sock);
+
+        Sockets[pos].Connected=true;
+
+        if (pos == SocketsNumber ) SocketsNumber++;
+
+        InitThreadOK=true;
     }
     catch ( SocketException& e )
     {
-      //A activer pour vÃ©rif
-      
-      /*std::string oss;
-      oss="pThreadSocket exception : " + e.description() + "\n";
-      size_t size = oss.size() + 1;
-      char* buffer = new char[size];
-      strncpy(buffer, oss.c_str(), size);
-      
-      IDLog(buffer);
-      
-      delete [] buffer;*/
-    }
-    
+        //A activer pour vÃ©rif
+
+        /*std::string oss;
+        oss="pThreadSocket exception : " + e.description() + "\n";
+        size_t size = oss.size() + 1;
+        char* buffer = new char[size];
+        strncpy(buffer, oss.c_str(), size);
+
+        IDLog(buffer);
+
+        delete [] buffer;*/
+    }
+
     return NULL;
-  }
-  
-  
-  /**************************************************************************************
-  ** Utilisation d'un thread pour Ã©viter de bloquer l'execution du pilote
-  ** avec la commande accept
-  ***************************************************************************************/
-  
-  void BAO::InitThread()
-  {
+}
+
+
+/**************************************************************************************
+** Utilisation d'un thread pour Ã©viter de bloquer l'execution du pilote
+** avec la commande accept
+***************************************************************************************/
+
+void BAO::InitThread()
+{
     if (pthread_create (&th1, NULL, pThreadSocket, NULL) < 0)
     {
-      IDLog("pthread_create error for threadSocket\n");
-    }
-    
+        IDLog("pthread_create error for threadSocket\n");
+    }
+
     pthread_join (th1, NULL);
-  }
-  
-  /**************************************************************************************
-  ** Initialisation du pilote BAO
-  ***************************************************************************************/
-  void ISInit()
-  {
+}
+
+/**************************************************************************************
+** Initialisation du pilote BAO
+***************************************************************************************/
+void ISInit()
+{
     static int isInit=0;
-    
+
     if (isInit) return;
-    
+
     if (telescope.get() == 0) telescope.reset(new BAO());
-    
+
     isInit = 1;
-    
+
     IEAddTimer (POLLMS, ISPoll, NULL);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISGetProperties (const char *dev)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISGetProperties (const char *dev)
+{
     ISInit();
     telescope->ISGetProperties(dev);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
     ISInit();
     telescope->ISNewSwitch(dev, name, states, names, n);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
     ISInit();
     telescope->ISNewText(dev, name, texts, names, n);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
     ISInit();
     telescope->ISNewNumber(dev, name, values, names, n);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISPoll (void *p)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISPoll (void *p)
+{
     INDI_UNUSED(p);
-    
+
     telescope->ISPoll();
     IEAddTimer (POLLMS, ISPoll, NULL);
-  }
-  
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
-  {
+}
+
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
+{
     INDI_UNUSED(dev);
     INDI_UNUSED(name);
@@ -196,23 +196,23 @@
     INDI_UNUSED(names);
     INDI_UNUSED(n);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void ISSnoopDevice (XMLEle *root)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISSnoopDevice (XMLEle *root)
+{
     INDI_UNUSED(root);
-  }
-  
-  /**************************************************************************************
-  ** Initialisation de la classe BAO
-  ***************************************************************************************/
-  BAO::BAO()
-  {
+}
+
+/**************************************************************************************
+** Initialisation de la classe BAO
+***************************************************************************************/
+BAO::BAO()
+{
     init_properties();
-    
+
     ConnectSP.s = IPS_IDLE;
-    
+
     lastSet        = -1;
     fd             = -1;
@@ -222,11 +222,11 @@
     currentSet     = 0;
     JJAnc          = 0.0;
-    
+
     SocketsNumber  = 1;
-    
+
     ActualisationTM1 = 15.0*60.0;
-    
+
     ActualisationTM2 = 5.0;
-    
+
     InitThreadOK=false;
     LecturePosition=false;
@@ -235,101 +235,101 @@
     Goto=false;
     LastGotoOK=true;
-    
+
     TrackingMode=1;
-    
+
     for (int i=0; i<MAXHOSTNAME; i++)
     {
-      Sockets[i].Connected=false;
-      Sockets[i].IP="";
-    }
-    
+        Sockets[i].Connected=false;
+        Sockets[i].IP="";
+    }
+
     InitAntennes();
-    
-    
+
+
     IDLog("Initilizing from BAO device...\n");
-    IDLog("Driver Version: 2010-05-12\n");
-    
+    IDLog("Driver Version: 2010-11-10\n");
+
     //enableSimulation(true);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  BAO::~BAO()
-  {
-    
-  }
-  
-  /**************************************************************************************
-  ** Initialisation des boutons et des zones d'affichage dans la boÃ®te de dialogue INDI
-  ***************************************************************************************/
-  void BAO::init_properties()
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+BAO::~BAO()
+{
+
+}
+
+/**************************************************************************************
+** Initialisation des boutons et des zones d'affichage dans la boÃ®te de dialogue INDI
+***************************************************************************************/
+void BAO::init_properties()
+{
     // Connection
     IUFillSwitch(&ConnectS[0], "CONNECT", "Connect", ISS_OFF);
     IUFillSwitch(&ConnectS[1], "DISCONNECT", "Disconnect", ISS_ON);
     IUFillSwitchVector(&ConnectSP, ConnectS, NARRAY(ConnectS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
-    
+
     // Coord Set
     IUFillSwitch(&OnCoordSetS[0], "TRANSIT", "Transit", ISS_ON);
     IUFillSwitch(&OnCoordSetS[1], "TRACKING", "Tracking", ISS_OFF);
     IUFillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
-    
+
     // Abort
     IUFillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
     IUFillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
-    
+
     // Park
     IUFillSwitch(&ParkS[0], "PARK", "Park", ISS_OFF);
     IUFillSwitchVector(&ParkSP, ParkS, NARRAY(ParkS), mydev, "", "Park", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
-    
+
     // Object Name
     IUFillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
     IUFillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
-    
-    
+
+
     // Equatorial Coords - SET
     IUFillNumber(&EquatorialCoordsWN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
     IUFillNumber(&EquatorialCoordsWN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
     IUFillNumberVector(&EquatorialCoordsWNP, EquatorialCoordsWN, NARRAY(EquatorialCoordsWN), mydev, "EQUATORIAL_EOD_COORD_REQUEST" , "Equatorial JNow", BASIC_GROUP, IP_WO, 0, IPS_IDLE);
-    
+
     // Equatorial Coords - READ
     //    IUFillNumber(&EquatorialCoordsRN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
     //    IUFillNumber(&EquatorialCoordsRN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
     //    IUFillNumberVector(&EquatorialCoordsRNP, EquatorialCoordsRN, NARRAY(EquatorialCoordsRN), mydev, "EQUATORIAL_EOD_COORD" , "Equatorial JNow", BASIC_GROUP, IP_RO, 0, IPS_IDLE);
-    
+
     // Geographic coord - SET
     IUFillNumber(&GeographicCoordsWN[0], "LAT", "Lat  D", "%10.6m",  -90., 90., 0., 0.);
     IUFillNumber(&GeographicCoordsWN[1], "LONG", "Long D", "%10.6m", 0., 360., 0., 0.);
     IUFillNumberVector(&GeographicCoordsWNP, GeographicCoordsWN, NARRAY(GeographicCoordsWN), mydev, "GEOGRAPHIC_COORD" , "Geographic coords", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
-    
+
     // Actualisation - SET
     IUFillNumber(&ActualisationN1[0], "DELAY", "Transit mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
     IUFillNumberVector(&ActualisationNP1, ActualisationN1, NARRAY(ActualisationN1), mydev, "DELAY1" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
-    
+
     IUFillNumber(&ActualisationN2[0], "DELAY", "Tracking mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
     IUFillNumberVector(&ActualisationNP2, ActualisationN2, NARRAY(ActualisationN2), mydev, "DELAY2" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
-    
+
     // Transit threshold
     //IUFillNumber(&SlewAccuracyN[0], "TransitRA",  "RA (arcmin)", "%10.6m",  0., 60., 1., 3.0);
     //IUFillNumber(&SlewAccuracyN[1], "TransitDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
     //IUFillNumberVector(&SlewAccuracyNP, SlewAccuracyN, NARRAY(SlewAccuracyN), mydev, "Transit Accuracy", "", OPTIONS_GROUP, IP_RW, 0, IPS_IDLE);
-    
+
     // Tracking threshold
     //IUFillNumber(&TrackAccuracyN[0], "TrackingRA", "RA (arcmin)", "%10.6m",  0., 60., 1., 3.0);
     //IUFillNumber(&TrackAccuracyN[1], "TrackingDEC", "Dec (arcmin)", "%10.6m", 0., 60., 1., 3.0);
     //IUFillNumberVector(&TrackAccuracyNP, TrackAccuracyN, NARRAY(TrackAccuracyN), mydev, "Tracking Accuracy", "", OPTIONS_GROUP, IP_RW, 0, IPS_IDLE);
-    
-  }
-  
-  /**************************************************************************************
-  ** Initialisation de la boÃ®te de dialogue INDI (suite)
-  ***************************************************************************************/
-  void BAO::ISGetProperties(const char *dev)
-  {
-    
+
+}
+
+/**************************************************************************************
+** Initialisation de la boÃ®te de dialogue INDI (suite)
+***************************************************************************************/
+void BAO::ISGetProperties(const char *dev)
+{
+
     if (dev && strcmp (mydev, dev))
-      return;
-    
+        return;
+
     // Main Control
     IDDefSwitch(&ConnectSP, NULL);
@@ -341,29 +341,29 @@
     IDDefSwitch(&AbortSlewSP, NULL);
     IDDefSwitch(&ParkSP, NULL);
-    
+
     // Options
     //IDDefNumber(&SlewAccuracyNP, NULL);
-    //IDDefNumber(&TrackAccuracyNP, NULL);   
+    //IDDefNumber(&TrackAccuracyNP, NULL);
     IDDefNumber(&ActualisationNP1, NULL);
     IDDefNumber(&ActualisationNP2, NULL);
-    
-  }
-  
-  /**************************************************************************************
-  ** En cas de changement de texte dans la boÃ®te de dialogue
-  ***************************************************************************************/
-  void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
-  {
+
+}
+
+/**************************************************************************************
+** En cas de changement de texte dans la boÃ®te de dialogue
+***************************************************************************************/
+void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
     // Ignore if not ours
     if (strcmp (dev, mydev))
-      return;
-    
+        return;
+
     if (is_connected() == false)
     {
-      IDMessage(mydev, "BAORadio. Please connect before issuing any commands.");
-      reset_all_properties();
-      return;
-    }
-    
+        IDMessage(mydev, "Error ! Please connect before issuing any commands.");
+        reset_all_properties();
+        return;
+    }
+
     // ===================================
     // Object Name
@@ -371,31 +371,31 @@
     if (!strcmp (name, ObjectTP.name))
     {
-      if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
-	return;
-      
-      ObjectTP.s = IPS_OK;
-      IDSetText(&ObjectTP, NULL);
-      return;
-    }
-  }
-  
-  /**************************************************************************************
-  ** En cas de changement d'une valeur numÃ©rique dans la boÃ®te de dialogue Indi
-  ***************************************************************************************/
-  void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
-  {
-    
+        if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
+            return;
+
+        ObjectTP.s = IPS_OK;
+        IDSetText(&ObjectTP, NULL);
+        return;
+    }
+}
+
+/**************************************************************************************
+** En cas de changement d'une valeur numÃ©rique dans la boÃ®te de dialogue Indi
+***************************************************************************************/
+void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
     // Ignore if not ours
     if (strcmp (dev, mydev))
-      return;
-    
+        return;
+
     if (is_connected() == false)
     {
-      IDMessage(mydev, "BAO is offline. Please connect before issuing any commands.");
-      reset_all_properties();
-      return;
-    }
-    
-    
+        IDMessage(mydev, "Error ! BAO is offline. Please connect before issuing any commands.");
+        reset_all_properties();
+        return;
+    }
+
+
     // ===================================
     // Geographic  Coords
@@ -403,49 +403,49 @@
     if (!strcmp (name, GeographicCoordsWNP.name))
     {
-      int i=0, nset=0, error_code=0;
-      
-      Latitude=0.0;
-      Longitude=0.0;
-      
-      for (nset = i = 0; i < n; i++)
-      {
-	INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
-	if (eqp == &GeographicCoordsWN[0])
-	{
-	  Latitude = values[i];
-	  nset += Latitude >= -90.0 && Latitude <= 90.0;
-	  
-	  Latitude*=Pidiv180;
-	}
-	else if (eqp == &GeographicCoordsWN[1])
-	{
-	  Longitude = values[i];
-	  nset += Longitude >= 0.0 && Longitude <= 360.0;
-	  
-	  Longitude*=-Pidiv180;
-	}
-      }
-      
-      if (nset == 2)
-      {
-	//VÃ©rification
-	//IDLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
-	
-	GeographicCoordsWNP.s = IPS_OK;
-	IDSetNumber(&GeographicCoordsWNP, NULL);
-      }
-      else
-      {
-	GeographicCoordsWNP.s = IPS_ALERT;
-	IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
-	
-	Latitude=0.0;
-	Longitude=0.0;
-      }
-      
-      return;
-    }
-    
-    
+        int i=0, nset=0, error_code=0;
+
+        Latitude=0.0;
+        Longitude=0.0;
+
+        for (nset = i = 0; i < n; i++)
+        {
+            INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
+            if (eqp == &GeographicCoordsWN[0])
+            {
+                Latitude = values[i];
+                nset += Latitude >= -90.0 && Latitude <= 90.0;
+
+                Latitude*=Pidiv180;
+            }
+            else if (eqp == &GeographicCoordsWN[1])
+            {
+                Longitude = values[i];
+                nset += Longitude >= 0.0 && Longitude <= 360.0;
+
+                Longitude*=-Pidiv180;
+            }
+        }
+
+        if (nset == 2)
+        {
+            //VÃ©rification
+            //IDLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
+
+            GeographicCoordsWNP.s = IPS_OK;
+            IDSetNumber(&GeographicCoordsWNP, NULL);
+        }
+        else
+        {
+            GeographicCoordsWNP.s = IPS_ALERT;
+            IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
+
+            Latitude=0.0;
+            Longitude=0.0;
+        }
+
+        return;
+    }
+
+
     // ===================================
     // Equatorial Coords
@@ -453,55 +453,55 @@
     if (!strcmp (name, EquatorialCoordsWNP.name))
     {
-      int i=0, nset=0, error_code=0;
-      double newRA =0, newDEC =0;
-      
-      for (nset = i = 0; i < n; i++)
-      {
-	INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
-	if (eqp == &EquatorialCoordsWN[0])
-	{
-	  newRA = values[i];	  
-	  nset += newRA >= 0 && newRA <= 24.0;
-	}
-	else if (eqp == &EquatorialCoordsWN[1])
-	{
-	  newDEC = values[i];
-	  nset += newDEC >= -90.0 && newDEC <= 90.0;
-	}
-      }
-      
-      targetRA  = newRA;
-      targetDEC = newDEC;
-      
-      if (nset == 2)
-      {
-	char RAStr[32], DecStr[32];
-	double targetAZ, targetAlt;
-	
-	fs_sexa(RAStr, newRA, 2, 3600);
-	fs_sexa(DecStr, newDEC, 2, 3600);
-	
-	IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
-	
-	// on convertit les coordonnÃ©es Ã©quatoriales de la zone du ciel observÃ©e
-	// en unitÃ©s de codeurs des moteurs
-	
-	ADDEC2Motor(newRA, newDEC);
-	
-	if (process_coords() == false)
-	{
-	  EquatorialCoordsWNP.s = IPS_ALERT;
-	  IDSetNumber(&EquatorialCoordsWNP, NULL);
-	}
-      }
-      else
-      {
-	EquatorialCoordsWNP.s = IPS_ALERT;
-	IDSetNumber(&EquatorialCoordsWNP, "RA or Dec missing or invalid");
-      }
-      
-      return;
-    }
-      
+        int i=0, nset=0, error_code=0;
+        double newRA =0, newDEC =0;
+
+        for (nset = i = 0; i < n; i++)
+        {
+            INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
+            if (eqp == &EquatorialCoordsWN[0])
+            {
+                newRA = values[i];
+                nset += newRA >= 0 && newRA <= 24.0;
+            }
+            else if (eqp == &EquatorialCoordsWN[1])
+            {
+                newDEC = values[i];
+                nset += newDEC >= -90.0 && newDEC <= 90.0;
+            }
+        }
+
+        targetRA  = newRA;
+        targetDEC = newDEC;
+
+        if (nset == 2)
+        {
+            char RAStr[32], DecStr[32];
+            double targetAZ, targetAlt;
+
+            fs_sexa(RAStr, newRA, 2, 3600);
+            fs_sexa(DecStr, newDEC, 2, 3600);
+
+            IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
+
+            // on convertit les coordonnÃ©es Ã©quatoriales de la zone du ciel observÃ©e
+            // en unitÃ©s de codeurs des moteurs
+
+            ADDEC2Motor(newRA, newDEC);
+
+            if (process_coords() == false)
+            {
+                EquatorialCoordsWNP.s = IPS_ALERT;
+                IDSetNumber(&EquatorialCoordsWNP, NULL);
+            }
+        }
+        else
+        {
+            EquatorialCoordsWNP.s = IPS_ALERT;
+            IDSetNumber(&EquatorialCoordsWNP, "Error ! RA or Dec missing or invalid");
+        }
+
+        return;
+    }
+
     // ===================================
     // Actualisation
@@ -509,70 +509,69 @@
     if (!strcmp (name, ActualisationNP1.name))
     {
-      int i=0, nset=0, error_code=0;
-      double newAct1 =0;
-      
-      for (nset = i = 0; i < n; i++)
-      {
-	INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
-	if (eqp == &ActualisationN1[0])
-	{
-	  newAct1 = values[i];
-	  
-	  if (newAct1 >= 0.0 && newAct1 <= 3600.0)
-	  {
-	    ActualisationTM1=newAct1;
-		
-	    ActualisationNP1.s = IPS_OK;
-	    IDSetNumber(&ActualisationNP1, NULL);
-          }
-          else
-          {
-	    ActualisationNP1.s = IPS_ALERT;
-	    IDSetNumber(&ActualisationNP1, "Delay invalid");
-          }
-	}
-      }
-      
-    }
-    
+        int i=0, nset=0, error_code=0;
+        double newAct1 =0;
+
+        for (nset = i = 0; i < n; i++)
+        {
+            INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
+            if (eqp == &ActualisationN1[0])
+            {
+                newAct1 = values[i];
+
+                if (newAct1 >= 0.0 && newAct1 <= 3600.0)
+                {
+                    ActualisationTM1=newAct1;
+
+                    ActualisationNP1.s = IPS_OK;
+                    IDSetNumber(&ActualisationNP1, NULL);
+                }
+                else
+                {
+                    ActualisationNP1.s = IPS_ALERT;
+                    IDSetNumber(&ActualisationNP1, "Error ! Delay invalid");
+                }
+            }
+        }
+    }
+
     if (!strcmp (name, ActualisationNP2.name))
     {
-      int i=0, nset=0, error_code=0;
-      double newAct2 =0;
-      
-      for (nset = i = 0; i < n; i++)
-      {
-	INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
-	if (eqp == &ActualisationN2[0])
-	{
-	  newAct2 = values[i];
-	  
-	  if (newAct2 >= 0.0 && newAct2 <= 3600.0)
-	  {
-	    ActualisationTM2=newAct2;
-		
-	    ActualisationNP2.s = IPS_OK;
-	    IDSetNumber(&ActualisationNP2, NULL);
-          }
-          else
-          {
-	    ActualisationNP2.s = IPS_ALERT;
-	    IDSetNumber(&ActualisationNP2, "Delay invalid");
-          }
-	}
-      }
-      
+        int i=0, nset=0, error_code=0;
+        double newAct2 =0;
+
+        for (nset = i = 0; i < n; i++)
+        {
+            INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
+            if (eqp == &ActualisationN2[0])
+            {
+                newAct2 = values[i];
+
+                if (newAct2 >= 0.0 && newAct2 <= 3600.0)
+                {
+                    ActualisationTM2=newAct2;
+
+                    ActualisationNP2.s = IPS_OK;
+                    IDSetNumber(&ActualisationNP2, NULL);
+                }
+                else
+                {
+                    ActualisationNP2.s = IPS_ALERT;
+                    IDSetNumber(&ActualisationNP2, "Error ! Delay invalid");
+                }
+            }
+        }
+
     } /* end EquatorialCoordsWNP */
-  }
-  
-  /**************************************************************************************
-  ** L'utilisateur clique sur l'un des boutons de la boÃ®te Indi
-  ***************************************************************************************/
-  void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
-  {
+}
+
+/**************************************************************************************
+** L'utilisateur clique sur l'un des boutons de la boÃ®te Indi
+***************************************************************************************/
+void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
     // ignore if not ours //
     if (strcmp (mydev, dev))
-      return;
-    
+        return;
+
     // ===================================
     // Connect Switch
@@ -580,18 +579,18 @@
     if (!strcmp (name, ConnectSP.name))
     {
-      if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
-	return;
-      
-      connect_telescope();
-      return;
-    }
-    
+        if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
+            return;
+
+        connect_telescope();
+        return;
+    }
+
     if (is_connected() == false)
     {
-      IDMessage(mydev, "BAORadio is offline. Please connect before issuing any commands.");
-      reset_all_properties();
-      return;
-    }
-    
+        IDMessage(mydev, "Error ! BAORadio is offline. Please connect before issuing any commands.");
+        reset_all_properties();
+        return;
+    }
+
     // ===================================
     // Coordinate Set
@@ -599,12 +598,12 @@
     if (!strcmp(name, OnCoordSetSP.name))
     {
-      if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
-	return;
-      
-      currentSet = get_switch_index(&OnCoordSetSP);
-      OnCoordSetSP.s = IPS_OK;
-      IDSetSwitch(&OnCoordSetSP, NULL);
-    }
-    
+        if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
+            return;
+
+        currentSet = get_switch_index(&OnCoordSetSP);
+        OnCoordSetSP.s = IPS_OK;
+        IDSetSwitch(&OnCoordSetSP, NULL);
+    }
+
     // ===================================
     // Abort slew
@@ -612,26 +611,26 @@
     if (!strcmp (name, AbortSlewSP.name))
     {
-      Abort=true;
-      
-      IUResetSwitch(&AbortSlewSP);
-      
-      /*
-      if (EquatorialCoordsWNP.s == IPS_BUSY)
-      {
-	
-	AbortSlewSP.s = IPS_OK;
-	EquatorialCoordsWNP.s       = IPS_IDLE;
-	EquatorialCoordsRNP.s       = IPS_IDLE;
-	HorizontalCoordsWNP.s       = IPS_IDLE;
-	IDSetSwitch(&AbortSlewSP, "Slew aborted.");
-	IDSetNumber(&EquatorialCoordsWNP, NULL);
-	IDSetNumber(&EquatorialCoordsRNP, NULL);
-	IDSetNumber(&HorizontalCoordsWNP, NULL);
-    }
-    */
-      return;
-    }
-    
-    
+        Abort=true;
+
+        IUResetSwitch(&AbortSlewSP);
+
+        /*
+        if (EquatorialCoordsWNP.s == IPS_BUSY)
+        {
+
+        AbortSlewSP.s = IPS_OK;
+        EquatorialCoordsWNP.s       = IPS_IDLE;
+        EquatorialCoordsRNP.s       = IPS_IDLE;
+        HorizontalCoordsWNP.s       = IPS_IDLE;
+        IDSetSwitch(&AbortSlewSP, "Slew aborted.");
+        IDSetNumber(&EquatorialCoordsWNP, NULL);
+        IDSetNumber(&EquatorialCoordsRNP, NULL);
+        IDSetNumber(&HorizontalCoordsWNP, NULL);
+        }
+        */
+        return;
+    }
+
+
     // ===================================
     // Park
@@ -639,51 +638,51 @@
     if (!strcmp (name, ParkSP.name))
     {
-      Park=true;
-      
-      IUResetSwitch(&ParkSP);
-      
-      /*
-      if (EquatorialCoordsWNP.s == IPS_BUSY)
-      {
-	
-	AbortSlewSP.s = IPS_OK;
-	EquatorialCoordsWNP.s       = IPS_IDLE;
-	EquatorialCoordsRNP.s       = IPS_IDLE;
-	HorizontalCoordsWNP.s       = IPS_IDLE;
-	IDSetSwitch(&AbortSlewSP, "Slew aborted.");
-	IDSetNumber(&EquatorialCoordsWNP, NULL);
-	IDSetNumber(&EquatorialCoordsRNP, NULL);
-	IDSetNumber(&HorizontalCoordsWNP, NULL);
-    }
-    */
-      return;
-    }
-  }
-  
-  /**************************************************************************************
-  ** fct peut-Ãªtre inutile
-  ***************************************************************************************/
-  void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
-  {
+        Park=true;
+
+        IUResetSwitch(&ParkSP);
+
+        /*
+        if (EquatorialCoordsWNP.s == IPS_BUSY)
+        {
+
+        AbortSlewSP.s = IPS_OK;
+        EquatorialCoordsWNP.s       = IPS_IDLE;
+        EquatorialCoordsRNP.s       = IPS_IDLE;
+        HorizontalCoordsWNP.s       = IPS_IDLE;
+        IDSetSwitch(&AbortSlewSP, "Slew aborted.");
+        IDSetNumber(&EquatorialCoordsWNP, NULL);
+        IDSetNumber(&EquatorialCoordsRNP, NULL);
+        IDSetNumber(&HorizontalCoordsWNP, NULL);
+        }
+        */
+        return;
+    }
+}
+
+/**************************************************************************************
+** fct peut-Ãªtre inutile
+***************************************************************************************/
+void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
+{
     nvp->s = IPS_ALERT;
-    
+
     /* If the error is a time out, then the device doesn't support this property */
     if (err == -2)
     {
-      nvp->s = IPS_ALERT;
-      IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+        nvp->s = IPS_ALERT;
+        IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
     }
     else
-      /* Changing property failed, user should retry. */
-      IDSetNumber( nvp , "%s failed.", msg);
-    
+        /* Changing property failed, user should retry. */
+        IDSetNumber( nvp , "%s failed.", msg);
+
     fault = true;
-  }
-  
-  /**************************************************************************************
-  ** Initialisation des vecteurs INDI
-  ***************************************************************************************/
-  void BAO::reset_all_properties()
-  {
+}
+
+/**************************************************************************************
+** Initialisation des vecteurs INDI
+***************************************************************************************/
+void BAO::reset_all_properties()
+{
     ConnectSP.s			= IPS_IDLE;
     OnCoordSetSP.s		= IPS_IDLE;
@@ -698,13 +697,13 @@
     ActualisationNP1.s		= IPS_IDLE;
     ActualisationNP2.s		= IPS_IDLE;
-    
+
     IUResetSwitch(&OnCoordSetSP);
     IUResetSwitch(&AbortSlewSP);
     IUResetSwitch(&ParkSP);
-    
+
     OnCoordSetS[0].s = ISS_ON;
     ConnectS[0].s = ISS_OFF;
     ConnectS[1].s = ISS_ON;
-    
+
     IDSetSwitch(&ConnectSP, NULL);
     IDSetSwitch(&OnCoordSetSP, NULL);
@@ -719,1013 +718,1010 @@
     IDSetNumber(&ActualisationNP1, NULL);
     IDSetNumber(&ActualisationNP2, NULL);
-   
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::correct_fault()
-  {
+
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::correct_fault()
+{
     fault = false;
     IDMessage(mydev, "Telescope is online.");
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  bool BAO::is_connected()
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+bool BAO::is_connected()
+{
     if (simulation) return true;
-    
+
     // return (ConnectSP.sp[0].s == ISS_ON);
     return (ConnectSP.s == IPS_OK);
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  static void retry_connection(void * p)
-  {
-    
-  }
-  
-  
-  /**************************************************************************************
-  ** Extraction de la position de l'antenne
-  ** dans le retour de la commande POS
-  ** POS/Valeur az/Valeur alt
-  ***************************************************************************************/
-  
-  Position BAO::ExtractPosition(std::string str)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+static void retry_connection(void * p)
+{
+
+}
+
+
+/**************************************************************************************
+** Extraction de la position de l'antenne
+** dans le retour de la commande POS
+** POS/Valeur az/Valeur alt
+***************************************************************************************/
+
+Position BAO::ExtractPosition(std::string str)
+{
     Position result;
-    
+
     std::string str2;
-    
+
     result.x = -1;
     result.y = -1;
-    
+
     int pos = str.find("/");
-    
+
     if (pos != string::npos)
     {
-      str2 = str.substr(pos+1);
-      
-      pos = str2.find("/");
-      
-      if (pos != string::npos)
-      {
-	result.x = atoi(str2.substr(0, pos).c_str());
-	
-	result.y = atoi(str2.substr(pos+1).c_str());
-      }
-    }
-    
+        str2 = str.substr(pos+1);
+
+        pos = str2.find("/");
+
+        if (pos != string::npos)
+        {
+            result.x = atoi(str2.substr(0, pos).c_str());
+
+            result.y = atoi(str2.substr(pos+1).c_str());
+        }
+    }
+
     return result;
-  }
-  
-  
-  
-  /************************************************************************************
-  * cette procÃ©dure convertit les coordonnÃ©es equatoriales de l'objet visÃ©
-  * en unitÃ©s de codeurs des paraboles (nb de tours des deux axes moteurs depuis la position PARK)
-  ************************************************************************************/
-  void BAO::ADDEC2Motor(double newRA, double newDEC)
-  {
+}
+
+
+
+/************************************************************************************
+* cette procÃ©dure convertit les coordonnÃ©es equatoriales de l'objet visÃ©
+* en unitÃ©s de codeurs des paraboles (nb de tours des deux axes moteurs depuis la position PARK)
+************************************************************************************/
+void BAO::ADDEC2Motor(double newRA, double newDEC)
+{
     double targetAz;
     double targetAlt;
     char AzStr[32];
     char AltStr[32];
-    
+
     // Calcule la hauteur et l'azimut de la zone du ciel pointÃ©e (en fonction de la date et du lieu)
-    
+
     Azimut(tsl, Latitude, newRA * 15.0 * Pidiv180, newDEC * Pidiv180, &targetAz, &targetAlt);
-    
+
     // En degrÃ©s
-    
+
     targetAlt *= N180divPi;
     targetAz *= N180divPi;
-    
+
     // Affichage dans les logs
-    
+
     fs_sexa(AzStr, targetAz, 2, 3600);
     fs_sexa(AltStr, targetAlt, 2, 3600);
-    
+
     IDLog("Horizontal coords : az %s - Alt %s\n", AzStr, AltStr);
-    
+
     // Le calcul est ici trÃšs sommaire et arbitraire :
     // Je considÃšre qu'il y a 100 positions possibles sur les deux axes
     // De plus, je considÃšre qu'il n'est pas possible de viser un objet Ã 
     // moins de 30Â° de hauteur au-dessus de l'horizon
-    
+
     TargetPosition.x=(int)(targetAz*100.0/360.0);
-    
+
     targetAlt=((90.0-targetAlt)/60.0);
-    
-    if (targetAlt>=1.0) 
-    {
-          targetAlt=1.0; //on ne peut pas viser un objet situÃ© Ã  moins de 30Â°
-          //au-dessus de l'horizon
-	  
-	  IDSetSwitch(&OnCoordSetSP, "Erreur : l objet suivi est situÃ© Ã  moins de 30Â° en-dessus de l horizon. Goto annulÃ©.");
-	  
-	  Goto=false;
-	  
-	  LecturePosition=false;
-	
-	  InitAntennes();
-    }
-  
+
+    if (targetAlt>=1.0)
+    {
+        targetAlt=1.0; //on ne peut pas viser un objet situÃ© Ã  moins de 30Â°
+        //au-dessus de l'horizon
+
+        IDSetSwitch(&OnCoordSetSP, "Erreur ! L objet suivi est situe a moins de 30Â° au-dessus de l horizon. Goto annule.");
+
+        Goto=false;
+
+        LecturePosition=false;
+
+        InitAntennes();
+    }
+
     TargetPosition.y=(int)(100.0*targetAlt);
-  }
-  
-  
-  /************************************************************************************
-  * Retourne simplement le nombre d'antennes connectÃ©es
-  * et capables de communiquer
-  ************************************************************************************/
-  
-  int BAO::AntennesConnectees()
-  {
+}
+
+
+/************************************************************************************
+* Retourne simplement le nombre d'antennes connectÃ©es
+* et capables de communiquer
+************************************************************************************/
+
+int BAO::AntennesConnectees()
+{
     int num=0;
-    
+
     for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected) num++;
-    
+
     return num;
-  }
-  
-  
-  /************************************************************************************
-  * Initialisation des paramÃštres des antennes
-  *
-  ************************************************************************************/
-  void BAO::InitAntennes()
-  {
+}
+
+
+/************************************************************************************
+* Initialisation des paramÃštres des antennes
+*
+************************************************************************************/
+void BAO::InitAntennes()
+{
     for (int i=0; i < MAXHOSTNAME ; i++)
     {
-      Sockets[i].status=0;
-      Sockets[i].sendalertes=0;
-      Sockets[i].AttenteExecution=0;
-      Sockets[i].AnomaliesExecution=0;
-      Sockets[i].etape=0;
-      
-      Sockets[i].ack_status=false;
-      Sockets[i].ack_pos=false;
-      Sockets[i].ack_park=false;
-      Sockets[i].ack_abort=false;
-      Sockets[i].ack_goto=false;
-      
-      Sockets[i].PosValides=false;
-      Sockets[i].GotoOk=false;
-    }
-  }
-  
-  
-  /**************************************************************************************
-  ** ProcÃ©dure principale
-  ** Elle est appelÃ©e toutes les POLLMS ms (ici 1 ms)
-  ***************************************************************************************/
-  void BAO::ISPoll()
-  {
+        Sockets[i].status=0;
+        Sockets[i].sendalertes=0;
+        Sockets[i].AttenteExecution=0;
+        Sockets[i].AnomaliesExecution=0;
+        Sockets[i].etape=0;
+
+        Sockets[i].ack_status=false;
+        Sockets[i].ack_pos=false;
+        Sockets[i].ack_park=false;
+        Sockets[i].ack_abort=false;
+        Sockets[i].ack_goto=false;
+
+        Sockets[i].PosValides=false;
+        Sockets[i].GotoOk=false;
+    }
+}
+
+
+/**************************************************************************************
+** ProcÃ©dure principale
+** Elle est appelÃ©e toutes les POLLMS ms (ici 1 ms)
+***************************************************************************************/
+void BAO::ISPoll()
+{
     static bool ISPOLLRunning=false;
     static int memSocketsNumber=-1;
     static unsigned int compt=100;
-    
+
     int pos;
-    
+
     struct tm date;
     time_t t;
     struct timeval tv;
     struct timezone tz;
-    
+
     if (is_connected() == false) return;
-    
+
     if (ISPOLLRunning) return;
-    
+
     ISPOLLRunning=true;
-    
+
     compt++;
-    
-    
+
+
     //toutes les 100 millisec
-    
+
     if ( compt%100 == 0)
     {
-      //RÃ©cupÃ©ration de la date et de l'heure
-      
-      time(&t);
-      date=*gmtime(&t);
-      gettimeofday(&tv, &tz);
-      
-      Annee=(double)(date.tm_year+1900);
-      Mois=(double)(date.tm_mon+1);
-      Jour=(double)date.tm_mday;
-      Heu=(double)date.tm_hour;
-      Min=(double)date.tm_min;
-      Sec=(double)date.tm_sec+tv.tv_usec/1.0E6;
-      UTCP=0.0;//(double)date.tm_isdst;
-      
-      
-      //Calcul du temps sidÃ©ral local
-      
-      CalculTSL();
-      
-      
-      //Y a-t-il de nouvelles tentatives de connexion sur le serveur ?
-      
-      InitThread();          
-    }
-    
-    
-    
-    
+        //RÃ©cupÃ©ration de la date et de l'heure
+
+        time(&t);
+        date=*gmtime(&t);
+        gettimeofday(&tv, &tz);
+
+        Annee=(double)(date.tm_year+1900);
+        Mois=(double)(date.tm_mon+1);
+        Jour=(double)date.tm_mday;
+        Heu=(double)date.tm_hour;
+        Min=(double)date.tm_min;
+        Sec=(double)date.tm_sec+tv.tv_usec/1.0E6;
+        UTCP=0.0;//(double)date.tm_isdst;
+
+
+        //Calcul du temps sidÃ©ral local
+
+        CalculTSL();
+
+
+        //Y a-t-il de nouvelles tentatives de connexion sur le serveur ?
+
+        InitThread();
+    }
+
+
+
+
     if (InitThreadOK)  // Il faut qu'il y ait eu au moins une connexion dÃ©tectÃ©e par le thread pour continuer
     {
-      
-      // Nouvelle connexion sur le socket !
-      
-      if (SocketsNumber>memSocketsNumber)
-      {
-	memSocketsNumber=SocketsNumber;
-	
-	IDSetSwitch(&ConnectSP, "Connexion de l antenne %s. (Antennes connectÃ©es : %i)",
-		    Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
-      }
-      
-      
-      
-      // DÃ©but des Ã©changes avec les microcontrÃŽleurs
-      
-      // Analyse des rÃ©ponses des microcontrÃŽleurs
-      
-      for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
-      {
-	try
-	{
-	  std::string reponse, memreponse;
-	  // on rÃ©cupÃšre la rÃ©ponse du microcontrÃŽleur
-	  
-	  Sockets[i].new_sock >> reponse;
-	  
-	  //IDSetSwitch(&OnCoordSetSP, "RÃ©ponse ISPOLL : %s\n", reponse.c_str());        // pour vÃ©rif
-	  
-	  //Dans le cas oÃ¹ plusieurs trames seraient arrivÃ©es entre deux appels de POLLMS
-	  //les traiter successivement
-	  
-	  pos=reponse.find("\n");   // d'oÃ¹ l'intÃ©rÃªt de mettre un '\n' Ã  la fin des trames
-	  //pour diffÃ©rencier une trame de la prÃ©cÃ©dente
-	  while ((pos!=string::npos) && (reponse.length()>1))
-	  {
-	    memreponse=reponse.substr(pos+1);
-	    
-	    reponse=reponse.substr(0, pos);
-	    
-	    
-	    // On traite ici les acknowledges
-	    
-	    if ((reponse.find("ACK")!=string::npos) && (reponse.find("NACK")==string::npos))
-	    {	      
-	      if (reponse.find("POS")!=string::npos)
-	      {
-		Sockets[i].ack_pos=true;
-	      }
-	      else if (reponse.find("GOTO")!=string::npos)
-	      {
-		Sockets[i].ack_goto=true;
-	      }
-	      else if (reponse.find("PARK")!=string::npos)
-	      {
-		Sockets[i].ack_park=true;
-	      }
-	      else if (reponse.find("ABORT")!=string::npos)
-	      {
-		Sockets[i].ack_abort=true;
-	      }
-	    }
-	    else
-	    {
-	      
-	      //rÃ©ponse Ã  la requÃªte POSITION
-	      if (reponse.find("POS")!=string::npos)
-	      {
-		if (reponse.find("NACK")!=string::npos)
-		{
-		  OnCoordSetSP.s = IPS_ALERT;
-		  IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
-			      Sockets[i].IP.c_str());
-			      Sockets[i].PosValides=false;
-			      // Si la position de l'antenne est inconnue, on dÃ©connecte l'antenne
-			      Sockets[i].Connected=false;
-		}
-		else if (Sockets[i].ack_pos)
-		{
-		  OnCoordSetSP.s = IPS_OK;
-		  Sockets[i].Pos = ExtractPosition(reponse);
-		  Sockets[i].PosValides = true;
-		  IDSetSwitch(&ParkSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
-		    Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
-		}
-		
-	      }//rÃ©ponse Ã  la requÃªte PARK
-	      else if (reponse.find("PARK")!=string::npos)
-	      {
-		if (reponse.find("NACK")!=string::npos)
-		{
-		  ParkSP.s = IPS_ALERT;
-		  IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
-		} 
-		else if (reponse.find("OK")!=string::npos)
-		{
-		  ParkSP.s = IPS_OK;
-		  IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
-		}
-		
-	      }//rÃ©ponse Ã  la requÃªte ABORT
-	      else if (reponse.find("ABORT")!=string::npos)
-	      {
-		if (reponse.find("NACK")!=string::npos)
-		{
-		  AbortSlewSP.s = IPS_ALERT;
-		  IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
-		}
-		
-		if (reponse.find("OK")!=string::npos)
-		{
-		  AbortSlewSP.s = IPS_OK;
-		  IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
-		}
-		
-	      } //rÃ©ponse Ã  la requÃªte GOTO
-	      else if (reponse.find("GOTO")!=string::npos)
-	      {
-		if (reponse.find("NACK")!=string::npos)
-		{
-		  OnCoordSetSP.s = IPS_ALERT;
-		  IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur GOTO !\n",  Sockets[i].IP.c_str());
-		  Sockets[i].Connected=false;
-		}
-		else if (Sockets[i].ack_goto)
-		{
-		  if (reponse.find("OK")!=string::npos)
-		  {
-		    OnCoordSetSP.s = IPS_OK;
-		  
-		    Sockets[i].GotoOk=true;
-		  
-		    IDSetSwitch(&ParkSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
-		  
-		    lastRA  = targetRA;
-		    lastDEC = targetDEC;
-		  
-		     //IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);*/
-		  
-		    EquatorialCoordsWNP.s = IPS_OK;
-		    IDSetNumber (&EquatorialCoordsWNP, NULL);
-		  
-		    // Fin du Goto pour toutes les antennes ?
-		  
-		    int num=0;
-		  
-		    for (int j=1; j<SocketsNumber; j++) if (Sockets[j].Connected)
-		    {
-		      if (Sockets[j].GotoOk) num++;
-		    }
-		  
-		    if ((num == AntennesConnectees()) && (num>0))
-		    {
-		      LecturePosition=false;
-		    
-		      InitAntennes();
-		      
-		      LastGotoOK=true;
-		    
-		      IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
-		    }
-		  }  
-		}
-	      }
-	    }
-	    
-	    // On passe Ã©ventuellement Ã  la trame suivante
-	    
-	    reponse=memreponse;
-	    pos=reponse.find("\n");
-	    
-	  }
-	}
-	catch (SocketException& e) //AÃ¯e
-	{
-	  Sockets[i].new_sock.shutdown();
-	  Sockets[i].new_sock.create();
-	  Sockets[i].Connected = Sockets[i].new_sock.connect((std::string)Sockets[i].IP);
-	  
-	  if (Sockets[i].Connected)
-	  {
-	    Sockets[i].AttenteExecution=0;
-	    Sockets[i].AnomaliesExecution=0;
-	  }  
-	  
-	  std::string oss;
-	  oss="SocketException IsPoll : " + e.description() + "\n";
-	  size_t size = oss.size() + 1;
-	  char* buffer = new char[size];
-	  strncpy(buffer, oss.c_str(), size);
-	  IDLog(buffer);
-	  delete [] buffer;
-	}
-      }
-      
-      
-      
-      if (Abort)
-      {
-	IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
-	
-	Goto=false;
-	
-	for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
-	{
-	  if (!ABORT(i)) Sockets[i].sendalertes++;
-	}
-	
-	LecturePosition=false;
-	
-	InitAntennes();
-	
-	Abort=false;
-      }
-      
-      
-      if (Park)
-      {
-	IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
-	
-	Goto=false;
-	
-	for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
-	{
-	  if (!PARK(i)) Sockets[i].sendalertes++;
-	}
-	
-	LecturePosition=false;
-	
-	InitAntennes();
-	
-	Park=false;
-      }
-      
-      
-      // Gestion du suivi
-      
-      if ((Goto) && (LastGotoOK))
-      {
-	// DurÃ©e entre deux actualisations
-	
-	double delai=ActualisationTM1/3600.0/24.0;   // Actualisation toutes les 15 minutes en mode transit
-	
-	if (TrackingMode==2) delai=ActualisationTM2/3600.0/24.0;   //et 5 secs en mode tracking
-	  
-	  
-	  // On actualise la position
-	  
-	  if (JJ-JJAnc > delai)
-	  {
-	    
-	    LastGotoOK=false;
-	    
-	    LecturePosition=true;
-	    
-	    ADDEC2Motor(targetRA, targetDEC);
-	    
-	    InitAntennes();	    
-	    
-	    JJAnc=JJ;
-	  }
-	  
-	  //Plus d'antenne !
-	  
-	  if (AntennesConnectees() == 0)
-	  {
-	    // LecturePosition=false;
-	    
-	    // Goto=false;
-	    
-	    // InitAntennes();
-	    
-	    if ( compt % 1000 == 0)  IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectÃ©es !");
-	  }
-      }
-      
-      
-      
-      // ExÃ©cution de la procÃ©dure complÃšte de lecture de la position de l'antenne
-      // puis envoi d'une commande Goto
-      
-      if (LecturePosition)
-      {
-	for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
-	{
-	  switch (Sockets[i].etape)
-	  {
-	   
-	    //Envoi de la commande POS
-	    case 0 :
-	    {
-	      Sockets[i].ack_pos=false;
-	      Sockets[i].PosValides=false;
-	      
-	      if (!POSITION(i)) Sockets[i].sendalertes++;
-	      
-	      Sockets[i].etape++;
-	    }
-	    break;
-	    
-	    //ack POS
-	    case 1 :
-	    {
-	      if (Sockets[i].ack_pos)
-	      {
-		Sockets[i].AttenteExecution=0;
-		Sockets[i].AnomaliesExecution=0;
-		Sockets[i].etape++;
-		i--;
-	      }
-	      else
-	      {
-		// on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
-		
-		Sockets[i].AttenteExecution++;
-		
-		if (Sockets[i].AttenteExecution>MAXATTENTE)
-		{
-		  Sockets[i].etape=0;
-		  Sockets[i].AttenteExecution=0;
-		  Sockets[i].AnomaliesExecution++;
-		}
-		
-		if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
-		{
-		  Sockets[i].etape=3;
-		  
-		 // if ( compt % 1000 == 0)
-		  {
-		    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. Pas d acknowledge reÃ§u aprÃšs l ordre POSITION. DÃ©connexion de l antenne.",
-				Sockets[i].IP.c_str());
-				Sockets[i].Connected=false;
-		  }
-		}
-	      }
-	    }
-	    break;
-	    
-	    //Valeurs pos valides ?
-	    case 2 :
-	    {
-	      if (Sockets[i].PosValides)
-	      {
-		Sockets[i].AttenteExecution=0;
-		Sockets[i].etape++;
-	      }
-	      else
-	      {
-		// on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
-		
-		Sockets[i].AttenteExecution++;
-		
-		if (Sockets[i].AttenteExecution>MAXATTENTE)
-		{
-		  Sockets[i].etape=2;
-		  Sockets[i].AttenteExecution=0;
-		  Sockets[i].AnomaliesExecution++;
-		}
-		
-		if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
-		{
-		  Sockets[i].etape=3;
-		  
-		 // if ( compt % 1000 == 0)
-		  {
-		    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. La position retournÃ©e n est pas valide. DÃ©connexion de l antenne.",
-				Sockets[i].IP.c_str());
-				Sockets[i].Connected=false;
-		  }
-		}
-	      }
-	    }
-	    break;
-	    
-	    //ack goto  ?
-	    case 4 :
-	    {
-	      if (Sockets[i].ack_goto)
-	      {
-		Sockets[i].AttenteExecution=0;
-		Sockets[i].AnomaliesExecution=0;
-		Sockets[i].etape++;
-	      }
-	      else
-	      {
-		// on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
-		
-		Sockets[i].AttenteExecution++;
-		
-		if (Sockets[i].AttenteExecution>MAXATTENTE)
-		{
-		  Sockets[i].etape=4;
-		  Sockets[i].AttenteExecution=0;
-		  Sockets[i].AnomaliesExecution++;
-		}
-		
-		if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
-		{
-		  Sockets[i].etape=6;
-		  
-		 // if ( compt % 1000 == 0)
-		  {
-		    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. Pas d acknowledge reÃ§u aprÃšs l ordre GOTO. DÃ©connexion de l antenne.",
-				Sockets[i].IP.c_str());
-				Sockets[i].Connected=false;
-		  }
-		}
-	      }
-	    }
-	    break;
-	    
-	    //goto ok  ?
-	    case 5 :
-	    {
-	      if (Sockets[i].GotoOk)
-	      {
-		Sockets[i].AttenteExecution=0;
-		Sockets[i].AnomaliesExecution=0;
-		Sockets[i].etape++;
-	      }
-	      else
-	      {
-		// on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
-		
-		Sockets[i].AttenteExecution++;
-		
-		if (Sockets[i].AttenteExecution>MAXATTENTE)
-		{
-		  Sockets[i].etape=5;
-		  Sockets[i].AttenteExecution=0;
-		  Sockets[i].AnomaliesExecution++;
-		}
-		
-		if (Sockets[i].AnomaliesExecution>MAXANOMALIESGOTO)
-		{
-		  Sockets[i].etape=6;
-		  
-		 // if ( compt % 1000 == 0)
-		  {
-		    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s. L antenne n a pas renvoyÃ© GOTO/OK. DÃ©connexion de l antenne.",
-				Sockets[i].IP.c_str());
-				Sockets[i].Connected=false;
-				
-				
-		  }
-		}
-	      }
-	    }
-	    break;
-	    
-	  }
-	}
-      }
-      
-      
-      
-      
-      
-      
-      // DÃ©tection d'anomalies concernant l'envoi de trames sur la socket. dÃ©connexion du micro-cont ?
-      
-      for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
-      {
-	if (Sockets[i].sendalertes > 0)
-	{
-	  Sockets[i].etape=5;
-	  
-	//  if ( compt % 1000 == 0)
-	  {
-	    IDSetSwitch(&OnCoordSetSP, "Anomalie dÃ©tectÃ©e sur l antenne %s. DÃ©connexion de l antenne.",
-			Sockets[i].IP.c_str());
-			
-			Sockets[i].Connected=false;
-	  }
-	}
-      }
-      
-      
-      
-      //On attend que toutes les antennes soient prÃªtes pour lancer l'ordre Goto -> meilleure synchronisation
-      
-      int num=0;
-      
-      for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
-      {
-	if (Sockets[i].etape == 3) num++; //fin de la procÃ©dure LecturePosition. Les antennes sont prÃªtes
-	  //Ã  recevoir l'ordre GOto
-      }
-      
-      if ((num == AntennesConnectees()) && (num>0))
-      {
-	for (int i=1; i<SocketsNumber; i++ ) if (Sockets[i].Connected)
-	{
-	  Sockets[i].ack_goto=false;
-	  Sockets[i].AttenteExecution=0;
-          Sockets[i].AnomaliesExecution=0;
-	  
-	  if (!GOTO(i, Sockets[i].Pos.x - TargetPosition.x, Sockets[i].Pos.y - TargetPosition.y )) Sockets[i].sendalertes++;
-	  
-	  Sockets[i].etape++;
-	}
-      }
-      
-      
-       
-    }
-    
+
+        // Nouvelle connexion sur le socket !
+
+        if (SocketsNumber>memSocketsNumber)
+        {
+            memSocketsNumber=SocketsNumber;
+
+            IDSetSwitch(&ConnectSP, "Connexion de l antenne %s. (Antennes connectees : %i)",
+                        Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
+        }
+
+
+
+        // DÃ©but des Ã©changes avec les microcontrÃŽleurs
+
+        // Analyse des rÃ©ponses des microcontrÃŽleurs
+
+        for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
+        {
+            try
+            {
+                std::string reponse, memreponse;
+                // on rÃ©cupÃšre la rÃ©ponse du microcontrÃŽleur
+
+                Sockets[i].new_sock >> reponse;
+
+                //IDSetSwitch(&OnCoordSetSP, "RÃ©ponse ISPOLL : %s\n", reponse.c_str());        // pour vÃ©rif
+
+                //Dans le cas oÃ¹ plusieurs trames seraient arrivÃ©es entre deux appels de POLLMS
+                //les traiter successivement
+
+                pos=reponse.find("\n");   // d'oÃ¹ l'intÃ©rÃªt de mettre un '\n' Ã  la fin des trames
+                //pour diffÃ©rencier une trame de la prÃ©cÃ©dente
+
+                while ((pos!=string::npos) && (reponse.length()>1))
+                {
+                    memreponse=reponse.substr(pos+1);
+
+                    reponse=reponse.substr(0, pos);
+
+
+                    // On traite ici les acknowledges
+
+                    if ((reponse.find("ACK")!=string::npos) && (reponse.find("NACK")==string::npos))
+                    {
+                        if (reponse.find("POSITION")!=string::npos)
+                        {
+                            Sockets[i].ack_pos=true;
+                        }
+                        else if (reponse.find("GOTO")!=string::npos)
+                        {
+                            Sockets[i].ack_goto=true;
+                        }
+                        else if (reponse.find("PARK")!=string::npos)
+                        {
+                            Sockets[i].ack_park=true;
+                        }
+                        else if (reponse.find("ABORT")!=string::npos)
+                        {
+                            Sockets[i].ack_abort=true;
+                        }
+                    }
+                    else
+                    {
+
+                        //rÃ©ponse Ã  la requÃªte POSITION
+                        if (reponse.find("POSITION")!=string::npos)
+                        {
+                            if (reponse.find("NACK")!=string::npos)
+                            {
+                                OnCoordSetSP.s = IPS_ALERT;
+                                IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
+                                            Sockets[i].IP.c_str());
+                                Sockets[i].PosValides=false;
+                                // Si la position de l'antenne est inconnue, on dÃ©connecte l'antenne
+                                Sockets[i].Connected=false;
+                            }
+                            else if (Sockets[i].ack_pos)
+                            {
+                                OnCoordSetSP.s = IPS_OK;
+                                Sockets[i].Pos = ExtractPosition(reponse);
+                                Sockets[i].PosValides = true;
+                                IDSetSwitch(&ParkSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
+                                            Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
+                            }
+
+                        }//rÃ©ponse Ã  la requÃªte PARK
+                        else if (reponse.find("PARK")!=string::npos)
+                        {
+                            if (reponse.find("NACK")!=string::npos)
+                            {
+                                ParkSP.s = IPS_ALERT;
+                                IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
+                            }
+                            else if (reponse.find("OK")!=string::npos)
+                            {
+                                ParkSP.s = IPS_OK;
+                                IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
+                            }
+
+                        }//rÃ©ponse Ã  la requÃªte ABORT
+                        else if (reponse.find("ABORT")!=string::npos)
+                        {
+                            if (reponse.find("NACK")!=string::npos)
+                            {
+                                AbortSlewSP.s = IPS_ALERT;
+                                IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
+                            }
+
+                            if (reponse.find("OK")!=string::npos)
+                            {
+                                AbortSlewSP.s = IPS_OK;
+                                IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
+                            }
+
+                        } //rÃ©ponse Ã  la requÃªte GOTO
+                        else if (reponse.find("GOTO")!=string::npos)
+                        {
+                            if (reponse.find("NACK")!=string::npos)
+                            {
+                                OnCoordSetSP.s = IPS_ALERT;
+                                IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur GOTO !\n",  Sockets[i].IP.c_str());
+                                Sockets[i].Connected=false;
+                            }
+                            else if (Sockets[i].ack_goto)
+                            {
+                                if (reponse.find("OK")!=string::npos)
+                                {
+                                    OnCoordSetSP.s = IPS_OK;
+
+                                    Sockets[i].GotoOk=true;
+
+                                    IDSetSwitch(&ParkSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
+
+                                    lastRA  = targetRA;
+                                    lastDEC = targetDEC;
+
+                                    //IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);*/
+
+                                    EquatorialCoordsWNP.s = IPS_OK;
+                                    IDSetNumber (&EquatorialCoordsWNP, NULL);
+
+                                    // Fin du Goto pour toutes les antennes ?
+
+                                    int num=0;
+
+                                    for (int j=1; j<SocketsNumber; j++) if (Sockets[j].Connected)
+                                        {
+                                            if (Sockets[j].GotoOk) num++;
+                                        }
+
+                                    if ((num == AntennesConnectees()) && (num>0))
+                                    {
+                                        LecturePosition=false;
+
+                                        InitAntennes();
+
+                                        LastGotoOK=true;
+
+                                        IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    // On passe Ã©ventuellement Ã  la trame suivante
+
+                    reponse=memreponse;
+                    pos=reponse.find("\n");
+
+                }
+            }
+            catch (SocketException& e) //AÃ¯e
+            {
+                Sockets[i].new_sock.shutdown();
+                Sockets[i].new_sock.create();
+                Sockets[i].Connected = Sockets[i].new_sock.connect((std::string)Sockets[i].IP);
+
+                if (Sockets[i].Connected)
+                {
+                    Sockets[i].AttenteExecution=0;
+                    Sockets[i].AnomaliesExecution=0;
+                }
+
+                std::string oss;
+                oss="SocketException IsPoll : " + e.description() + "\n";
+                size_t size = oss.size() + 1;
+                char* buffer = new char[size];
+                strncpy(buffer, oss.c_str(), size);
+                IDLog(buffer);
+                delete [] buffer;
+            }
+        }
+
+
+
+        if (Abort)
+        {
+            IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
+
+            Goto=false;
+
+            for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
+                {
+                    if (!ABORT(i)) Sockets[i].sendalertes++;
+                }
+
+            LecturePosition=false;
+
+            InitAntennes();
+
+            Abort=false;
+        }
+
+
+        if (Park)
+        {
+            IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
+
+            Goto=false;
+
+            for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
+                {
+                    if (!PARK(i)) Sockets[i].sendalertes++;
+                }
+
+            LecturePosition=false;
+
+            InitAntennes();
+
+            Park=false;
+        }
+
+
+        // Gestion du suivi
+
+        if ((Goto) && (LastGotoOK))
+        {
+            // DurÃ©e entre deux actualisations
+
+            double delai=ActualisationTM1/3600.0/24.0;   // Actualisation toutes les 15 minutes en mode transit
+
+            if (TrackingMode==2) delai=ActualisationTM2/3600.0/24.0;   //et 5 secs en mode tracking
+
+
+            // On actualise la position
+
+            if (JJ-JJAnc > delai)
+            {
+
+                LastGotoOK=false;
+
+                LecturePosition=true;
+
+                ADDEC2Motor(targetRA, targetDEC);
+
+                InitAntennes();
+
+                JJAnc=JJ;
+            }
+
+            //Plus d'antenne !
+
+            if (AntennesConnectees() == 0)
+            {
+                // LecturePosition=false;
+
+                // Goto=false;
+
+                // InitAntennes();
+
+                if ( compt % 1000 == 0)  IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectees !");
+            }
+        }
+
+
+
+        // ExÃ©cution de la procÃ©dure complÃšte de lecture de la position de l'antenne
+        // puis envoi d'une commande Goto
+
+        if (LecturePosition)
+        {
+            for (int i=1; i<SocketsNumber; i++) /*if (Sockets[i].Connected)*/
+            {
+                switch (Sockets[i].etape)
+                {
+
+                    //Envoi de la commande POS
+                case 0 :
+                {
+                    Sockets[i].ack_pos=false;
+                    Sockets[i].PosValides=false;
+
+                    if (!POSITION(i)) Sockets[i].sendalertes++;
+
+                    Sockets[i].etape++;
+                }
+                break;
+
+                //ack POS
+                case 1 :
+                {
+                    if (Sockets[i].ack_pos)
+                    {
+                        Sockets[i].AttenteExecution=0;
+                        Sockets[i].AnomaliesExecution=0;
+                        Sockets[i].etape++;
+                        i--;
+                    }
+                    else
+                    {
+                        // on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
+
+                        Sockets[i].AttenteExecution++;
+
+                        if (Sockets[i].AttenteExecution>MAXATTENTE)
+                        {
+                            Sockets[i].etape=0;
+                            Sockets[i].AttenteExecution=0;
+                            Sockets[i].AnomaliesExecution++;
+                        }
+
+                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
+                        {
+                            Sockets[i].etape=3;
+
+                            // if ( compt % 1000 == 0)
+                            {
+                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre POSITION. \
+                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
+                                Sockets[i].Connected=false;
+                            }
+                        }
+                    }
+                }
+                break;
+
+                //Valeurs pos valides ?
+                case 2 :
+                {
+                    if (Sockets[i].PosValides)
+                    {
+                        Sockets[i].AttenteExecution=0;
+                        Sockets[i].etape++;
+                    }
+                    else
+                    {
+                        // on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
+
+                        Sockets[i].AttenteExecution++;
+
+                        if (Sockets[i].AttenteExecution>MAXATTENTE)
+                        {
+                            Sockets[i].etape=2;
+                            Sockets[i].AttenteExecution=0;
+                            Sockets[i].AnomaliesExecution++;
+                        }
+
+                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
+                        {
+                            Sockets[i].etape=3;
+
+                            // if ( compt % 1000 == 0)
+                            {
+                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : la position retournee n est pas valide. \
+                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
+                                Sockets[i].Connected=false;
+                            }
+                        }
+                    }
+                }
+                break;
+
+                //ack goto  ?
+                case 4 :
+                {
+                    if (Sockets[i].ack_goto)
+                    {
+                        Sockets[i].AttenteExecution=0;
+                        Sockets[i].AnomaliesExecution=0;
+                        Sockets[i].etape++;
+                    }
+                    else
+                    {
+                        // on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
+
+                        Sockets[i].AttenteExecution++;
+
+                        if (Sockets[i].AttenteExecution>MAXATTENTE)
+                        {
+                            Sockets[i].etape=4;
+                            Sockets[i].AttenteExecution=0;
+                            Sockets[i].AnomaliesExecution++;
+                        }
+
+                        if (Sockets[i].AnomaliesExecution>MAXANOMALIES)
+                        {
+                            Sockets[i].etape=6;
+
+                            // if ( compt % 1000 == 0)
+                            {
+                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre GOTO. \
+                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
+                                Sockets[i].Connected=false;
+                            }
+                        }
+                    }
+                }
+                break;
+
+                //goto ok  ?
+                case 5 :
+                {
+                    if (Sockets[i].GotoOk)
+                    {
+                        Sockets[i].AttenteExecution=0;
+                        Sockets[i].AnomaliesExecution=0;
+                        Sockets[i].etape++;
+                    }
+                    else
+                    {
+                        // on rÃ©itÃšre l'ordre prÃ©cÃ©dent si rien ne se passe
+
+                        Sockets[i].AttenteExecution++;
+
+                        if (Sockets[i].AttenteExecution>MAXATTENTE)
+                        {
+                            Sockets[i].etape=5;
+                            Sockets[i].AttenteExecution=0;
+                            Sockets[i].AnomaliesExecution++;
+                        }
+
+                        if (Sockets[i].AnomaliesExecution>MAXANOMALIESGOTO)
+                        {
+                            Sockets[i].etape=6;
+
+                            // if ( compt % 1000 == 0)
+                            {
+                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : l antenne n a pas renvoye GOTO/OK. \
+                                Deconnexion de l antenne.", Sockets[i].IP.c_str());
+                                Sockets[i].Connected=false;
+
+
+                            }
+                        }
+                    }
+                }
+                break;
+
+                }
+            }
+        }
+
+
+
+
+
+
+        // DÃ©tection d'anomalies concernant l'envoi de trames sur la socket. dÃ©connexion du micro-cont ?
+
+        for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
+            {
+                if (Sockets[i].sendalertes > 0)
+                {
+                    Sockets[i].etape=5;
+
+                    //  if ( compt % 1000 == 0)
+                    {
+                        IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : deconnexion de l antenne.", Sockets[i].IP.c_str());
+
+                        Sockets[i].Connected=false;
+                    }
+                }
+            }
+
+
+
+        //On attend que toutes les antennes soient prÃªtes pour lancer l'ordre Goto -> meilleure synchronisation
+
+        int num=0;
+
+        for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected)
+            {
+                if (Sockets[i].etape == 3) num++; //fin de la procÃ©dure LecturePosition. Les antennes sont prÃªtes
+                //Ã  recevoir l'ordre GOto
+            }
+
+        if ((num == AntennesConnectees()) && (num>0))
+        {
+            for (int i=1; i<SocketsNumber; i++ ) if (Sockets[i].Connected)
+                {
+                    Sockets[i].ack_goto=false;
+                    Sockets[i].AttenteExecution=0;
+                    Sockets[i].AnomaliesExecution=0;
+
+                    if (!GOTO(i, Sockets[i].Pos.x - TargetPosition.x, Sockets[i].Pos.y - TargetPosition.y )) Sockets[i].sendalertes++;
+
+                    Sockets[i].etape++;
+                }
+        }
+    }
+
     ISPOLLRunning=false;
-  }
-  
-  
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  bool BAO::process_coords()
-  {
+}
+
+
+
+/**************************************************************************************
+**
+***************************************************************************************/
+bool BAO::process_coords()
+{
     switch (currentSet)
     {
-      // Transit
-      case BAO_TRANSIT:
-	
-	EquatorialCoordsWNP.s = IPS_BUSY;
-	
-	IDSetNumber (&EquatorialCoordsWNP, NULL);
-	
-	InitAntennes();
-	
-	JJAnc=JJ;
-	
-	TrackingMode = 1;
-	
-	Goto=true;
-	
-	LastGotoOK=false;
-	
-	LecturePosition=true;
-	
-	ADDEC2Motor(targetRA, targetDEC);
-	
-	break;
-	
-	// Tracking
-      case BAO_TRACKING:
-	
-	EquatorialCoordsWNP.s = IPS_BUSY;
-	
-	IDSetNumber (&EquatorialCoordsWNP, NULL);
-	
-	InitAntennes();
-	
-	JJAnc=JJ;
-	
-	TrackingMode = 2;
-	
-	Goto=true;
-	
-	LastGotoOK=false;
-	
-	LecturePosition=true;
-	
-	ADDEC2Motor(targetRA, targetDEC);
-	
-	break;
-    }
-    
+        // Transit
+    case BAO_TRANSIT:
+
+        EquatorialCoordsWNP.s = IPS_BUSY;
+
+        IDSetNumber (&EquatorialCoordsWNP, NULL);
+
+        InitAntennes();
+
+        JJAnc=JJ;
+
+        TrackingMode = 1;
+
+        Goto=true;
+
+        LastGotoOK=false;
+
+        LecturePosition=true;
+
+        ADDEC2Motor(targetRA, targetDEC);
+
+        break;
+
+        // Tracking
+    case BAO_TRACKING:
+
+        EquatorialCoordsWNP.s = IPS_BUSY;
+
+        IDSetNumber (&EquatorialCoordsWNP, NULL);
+
+        InitAntennes();
+
+        JJAnc=JJ;
+
+        TrackingMode = 2;
+
+        Goto=true;
+
+        LastGotoOK=false;
+
+        LecturePosition=true;
+
+        ADDEC2Motor(targetRA, targetDEC);
+
+        break;
+    }
+
     return true;
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  int BAO::get_switch_index(ISwitchVectorProperty *sp)
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+int BAO::get_switch_index(ISwitchVectorProperty *sp)
+{
     for (int i=0; i < sp->nsp ; i++)
-      if (sp->sp[i].s == ISS_ON)
-	return i;
-      
-      return -1;
-  }
-  
-  /**************************************************************************************
-  ** Activation de l'interface
-  ***************************************************************************************/
-  void BAO::connect_telescope()
-  {
+        if (sp->sp[i].s == ISS_ON)
+            return i;
+
+    return -1;
+}
+
+/**************************************************************************************
+** Activation de l'interface
+***************************************************************************************/
+void BAO::connect_telescope()
+{
     switch (ConnectSP.sp[0].s)
     {
-      case ISS_ON:
-	ConnectS[0].s = ISS_ON;
-	ConnectS[1].s = ISS_OFF;
-	IDLog("\nHello BAORadio !\n");
-	
-	ConnectSP.s = IPS_OK;
-	IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
-	
-	
-	break;
-	
-      case ISS_OFF:
-	ConnectS[0].s = ISS_OFF;
-	ConnectS[1].s = ISS_ON;
-	ConnectSP.s = IPS_IDLE;
-	
-	SocketsNumber=1;
-	InitThreadOK=false;
-	
-	for (int i=0; i<MAXHOSTNAME; i++)
-	{
-	  Sockets[i].Connected=false;
-	  Sockets[i].IP="";
-	  Sockets[i].new_sock.shutdown();
-	}
-	
-	InitAntennes();
-	
-	IDSetSwitch (&ConnectSP, "BAORadio is offline.");
-	IDLog("Telescope is offline.");
-	
-	break;
-    }
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::get_initial_data()
-  {
+    case ISS_ON:
+        ConnectS[0].s = ISS_ON;
+        ConnectS[1].s = ISS_OFF;
+        IDLog("\nHello BAORadio !\n");
+
+        ConnectSP.s = IPS_OK;
+        IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
+
+
+        break;
+
+    case ISS_OFF:
+        ConnectS[0].s = ISS_OFF;
+        ConnectS[1].s = ISS_ON;
+        ConnectSP.s = IPS_IDLE;
+
+        SocketsNumber=1;
+        InitThreadOK=false;
+
+        for (int i=0; i<MAXHOSTNAME; i++)
+        {
+            Sockets[i].Connected=false;
+            Sockets[i].IP="";
+            Sockets[i].new_sock.shutdown();
+        }
+
+        InitAntennes();
+
+        IDSetSwitch (&ConnectSP, "BAORadio is offline.");
+        IDLog("Telescope is offline.");
+
+        break;
+    }
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::get_initial_data()
+{
     //  IDSetNumber (&EquatorialCoordsRNP, NULL);
-    
-     
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::slew_error(int slewCode)
-  {
+
+
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::slew_error(int slewCode)
+{
     OnCoordSetSP.s = IPS_IDLE;
-    
+
     if (slewCode == 1)
-      IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
+        IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
     else if (slewCode == 2)
-      IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
+        IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
     else
-      IDSetSwitch (&OnCoordSetSP, "Slew failed.");
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::enable_simulation(bool enable)
-  {
+        IDSetSwitch (&OnCoordSetSP, "Slew failed.");
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::enable_simulation(bool enable)
+{
     simulation = enable;
-    
+
     if (simulation)
-      IDLog("Warning: Simulation is activated.\n");
+        IDLog("Warning: Simulation is activated.\n");
     else
-      IDLog("Simulation is disabled.\n");
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::connection_lost()
-  {
+        IDLog("Simulation is disabled.\n");
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::connection_lost()
+{
     ConnectSP.s = IPS_IDLE;
     IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
     return;
-  }
-  
-  /**************************************************************************************
-  **
-  ***************************************************************************************/
-  void BAO::connection_resumed()
-  {
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void BAO::connection_resumed()
+{
     ConnectS[0].s = ISS_ON;
     ConnectS[1].s = ISS_OFF;
     ConnectSP.s = IPS_OK;
-    
+
     IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
-  }
-  
-  
-  /**************************************************************************************
-  **  Envoi d'une commande sur le socket puis attente de l'acknowledge
-  ***************************************************************************************/
-  
-  bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
-  {
+}
+
+
+/**************************************************************************************
+**  Envoi d'une commande sur le socket puis attente de l'acknowledge
+***************************************************************************************/
+
+bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
+{
     char chaine[MAXCARACTERES];
-    
+
     try
     {
-      sprintf(chaine, "%s%s\n", Commande, Params);
-      
-      Sockets[numsocket].new_sock << chaine;
+        sprintf(chaine, "%s%s\n", Commande, Params);
+
+        Sockets[numsocket].new_sock << chaine;
     }
     catch (SocketException& e)
-    {        
-      Sockets[numsocket].new_sock.shutdown();
-      Sockets[numsocket].new_sock.create();
-      Sockets[numsocket].Connected = Sockets[numsocket].new_sock.connect((std::string)Sockets[numsocket].IP);
-      
-      if (Sockets[numsocket].Connected)
-      {
-	Sockets[numsocket].AttenteExecution=0;
-	Sockets[numsocket].AnomaliesExecution=0;
-      }
-      
-      //  if (AntennesConnectees() == 0) { InitAntennes(); InitThreadOK=false;}
-      
-      std::string oss;
-      oss="COMMANDE exception : " + e.description() + "\n";
-      size_t size = oss.size() + 1;
-      char* buffer = new char[size];
-      strncpy(buffer, oss.c_str(), size);
-      
-      IDLog(buffer);
-      
-      delete [] buffer;
-      
-      return false;
-    }
-    
+    {
+        Sockets[numsocket].new_sock.shutdown();
+        Sockets[numsocket].new_sock.create();
+        Sockets[numsocket].Connected = Sockets[numsocket].new_sock.connect((std::string)Sockets[numsocket].IP);
+
+        if (Sockets[numsocket].Connected)
+        {
+            Sockets[numsocket].AttenteExecution=0;
+            Sockets[numsocket].AnomaliesExecution=0;
+        }
+
+        //  if (AntennesConnectees() == 0) { InitAntennes(); InitThreadOK=false;}
+
+        std::string oss;
+        oss="COMMANDE exception : " + e.description() + "\n";
+        size_t size = oss.size() + 1;
+        char* buffer = new char[size];
+        strncpy(buffer, oss.c_str(), size);
+
+        IDLog(buffer);
+
+        delete [] buffer;
+
+        return false;
+    }
+
     return true;
-  }
-  
-  
-  /**************************************************************************************
-  ** Commande POSITION
-  ***************************************************************************************/
-  
-  bool BAO::POSITION(int numsocket)
-  {
+}
+
+
+/**************************************************************************************
+** Commande POSITION
+***************************************************************************************/
+
+bool BAO::POSITION(int numsocket)
+{
     return COMMANDE(numsocket, (char*)"P", (char*)"");
-  }
-  
-  /**************************************************************************************
-  ** Commande PARK
-  ***************************************************************************************/
-  
-  bool BAO::PARK(int numsocket)
-  {
+}
+
+/**************************************************************************************
+** Commande PARK
+***************************************************************************************/
+
+bool BAO::PARK(int numsocket)
+{
     return COMMANDE(numsocket, (char*)"Z", (char*)"");
-  }
-  
-  /**************************************************************************************
-  ** Commande ABORT
-  ***************************************************************************************/
-  
-  bool BAO::ABORT(int numsocket)
-  {
+}
+
+/**************************************************************************************
+** Commande ABORT
+***************************************************************************************/
+
+bool BAO::ABORT(int numsocket)
+{
     return COMMANDE(numsocket, (char*)"A", (char*)"");
-  }
-  
-  
-  /**************************************************************************************
-  ** Commande GOTO
-  ***************************************************************************************/
-  
-  bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
-  {
+}
+
+
+/**************************************************************************************
+** Commande GOTO
+***************************************************************************************/
+
+bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
+{
     char Params[MAXCARACTERES];
     char sensAz;
     char sensAlt;
-    
+
     sensAlt='b';
     sensAz='b';
-    
+
     if (deltaAz<0)
     {
-      deltaAz=-deltaAz;
-      sensAz='f';
-    }
-    
+        deltaAz=-deltaAz;
+        sensAz='f';
+    }
+
     if (deltaAlt<0)
     {
-      deltaAlt=-deltaAlt;
-      sensAlt='f';
-    }
-    
+        deltaAlt=-deltaAlt;
+        sensAlt='f';
+    }
+
     sprintf(Params, "%c%04i%c%04i", sensAz, deltaAz, sensAlt, deltaAlt);
-    
+
     return COMMANDE(numsocket, (char*)"G", Params);
-  }
-  
-  
-  
+}
+
+
+
Index: /BAORadio/libindi/libindi/drivers/telescope/lx200basic.cpp
===================================================================
--- /BAORadio/libindi/libindi/drivers/telescope/lx200basic.cpp	(revision 500)
+++ /BAORadio/libindi/libindi/drivers/telescope/lx200basic.cpp	(revision 501)
@@ -163,6 +163,7 @@
    IDLog("Driver Version: 2007-09-28\n");
  
-   //enableSimulation(true);  
-}
+   enable_simulation(false);  
+
+ }
 
 /**************************************************************************************
@@ -342,5 +343,5 @@
            #endif
 	   
-	   if ( (error_code = setObjectRA(fd, newRA)) < 0 || ( error_code = setObjectDEC(fd, newDEC)) < 0)
+	   if (!simulation && ( (error_code = setObjectRA(fd, newRA)) < 0 || ( error_code = setObjectDEC(fd, newDEC)) < 0))
 	   {
 	     handle_error(&EquatorialCoordsWNP, error_code, "Setting RA/DEC");
@@ -574,5 +575,5 @@
 void LX200Basic::ISPoll()
 {	
-	if (is_connected() == false)
+	if (is_connected() == false || simulation)
 	 return;
 
@@ -684,5 +685,5 @@
 	  }
 
-	  if ((error_code = Slew(fd)))
+	  if ( !simulation && (error_code = Slew(fd)))
 	  {
 	    slew_error(error_code);
@@ -716,5 +717,5 @@
 	  if (dx >= (TrackAccuracyN[0].value/(60.0*15.0)) || (dy >= TrackAccuracyN[1].value/60.0)) 
 	  {
-          	if ((error_code = Slew(fd)))
+          	if ( !simulation && (error_code = Slew(fd)))
 	  	{
 	    		slew_error(error_code);
@@ -751,8 +752,14 @@
 	  EquatorialCoordsWNP.s = IPS_IDLE;
 	   
-	  if ( ( error_code = Sync(fd, syncString) < 0) )
+	  if ( !simulation && ( error_code = Sync(fd, syncString) < 0) )
 	  {
 	        IDSetNumber( &EquatorialCoordsWNP , "Synchronization failed.");
 		return false;
+	  }
+
+	  if (simulation)
+	  {
+             EquatorialCoordsRN[0].value = EquatorialCoordsWN[0].value;
+             EquatorialCoordsRN[1].value = EquatorialCoordsWN[1].value;
 	  }
 
Index: /BAORadio/libindi/libindi/drivers/telescope/lx200generic.cpp
===================================================================
--- /BAORadio/libindi/libindi/drivers/telescope/lx200generic.cpp	(revision 500)
+++ /BAORadio/libindi/libindi/drivers/telescope/lx200generic.cpp	(revision 501)
@@ -165,4 +165,5 @@
  Property: Movement (Arrow keys on handset). West/East
 *********************************************/
+
 static ISwitch MovementWES[]       = {{"MOTION_WEST", "West", ISS_OFF, 0, 0}, {"MOTION_EAST", "East", ISS_OFF, 0, 0}};
 ISwitchVectorProperty MovementWESP      = { mydev, "TELESCOPE_MOTION_WE", "West/East", MOTION_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, MovementWES, NARRAY(MovementWES), "", 0};
@@ -314,4 +315,5 @@
   strcpy(TimeTP.device , newName );
   strcpy(UTCOffsetNP.device , newName );
+
   strcpy(SDTimeNP.device , newName );
 
@@ -338,4 +340,5 @@
 {
   static int isInit=0;
+  char *envDev = getenv("INDIDEV");
 
  if (isInit)
@@ -355,9 +358,17 @@
   {
      fprintf(stderr , "initilizaing from LX200 classic device...\n");
-     // 1. mydev = device_name
-     changeAllDeviceNames("LX200 Classic");
-     // 2. device = sub_class
+
      telescope = new LX200Classic();
-     telescope->setCurrentDeviceName("LX200 Classic");
+     if (envDev != NULL)
+     {
+         changeAllDeviceNames(envDev);
+         telescope->setCurrentDeviceName(envDev);
+     }
+     else
+     {
+        // 1. mydev = device_name
+        changeAllDeviceNames("LX200 Classic");
+        telescope->setCurrentDeviceName("LX200 Classic");
+     }
 
      MaxReticleFlashRate = 3;
@@ -367,9 +378,22 @@
   {
      fprintf(stderr , "initilizaing from LX200 GPS device...\n");
-     // 1. mydev = device_name
-     changeAllDeviceNames("LX200 GPS");
+
      // 2. device = sub_class
      telescope = new LX200GPS();
-     telescope->setCurrentDeviceName("LX200 GPS");
+
+     if (envDev != NULL)
+     {
+         // 1. mydev = device_name
+         changeAllDeviceNames(envDev);
+         telescope->setCurrentDeviceName(envDev);
+     }
+     else
+     {
+         // 1. mydev = device_name
+         changeAllDeviceNames("LX200 GPS");
+         telescope->setCurrentDeviceName("LX200 GPS");
+     }
+
+
 
      MaxReticleFlashRate = 9;
@@ -379,9 +403,19 @@
 
     IDLog("Initilizaing from LX200 16 device...\n");
-    // 1. mydev = device_name
-    changeAllDeviceNames("LX200 16");
+
     // 2. device = sub_class
    telescope = new LX200_16();
-   telescope->setCurrentDeviceName("LX200 16");
+
+   if (envDev != NULL)
+   {
+       // 1. mydev = device_name
+       changeAllDeviceNames(envDev);
+       telescope->setCurrentDeviceName(envDev);
+   }
+   else
+   {
+       changeAllDeviceNames("LX200 16");
+       telescope->setCurrentDeviceName("LX200 16");
+   }
 
    MaxReticleFlashRate = 3;
@@ -391,9 +425,19 @@
    fprintf(stderr , "initilizaing from autostar device...\n");
   
-   // 1. change device name
-   changeAllDeviceNames("LX200 Autostar");
    // 2. device = sub_class
    telescope = new LX200Autostar();
-   telescope->setCurrentDeviceName("LX200 Autostar");
+
+   if (envDev != NULL)
+   {
+       // 1. change device name
+       changeAllDeviceNames(envDev);
+       telescope->setCurrentDeviceName(envDev);
+   }
+   else
+   {
+       // 1. change device name
+       changeAllDeviceNames("LX200 Autostar");
+       telescope->setCurrentDeviceName("LX200 Autostar");
+   }
 
    MaxReticleFlashRate = 9;
@@ -403,9 +447,21 @@
    fprintf(stderr , "initilizaing from ap device...\n");
   
-   // 1. change device name
-   changeAllDeviceNames("LX200 Astro-Physics");
+
    // 2. device = sub_class
    telescope = new LX200AstroPhysics();
-   telescope->setCurrentDeviceName("LX200 Astro-Physics");
+
+   if (envDev != NULL)
+   {
+       // 1. change device name
+       changeAllDeviceNames(envDev);
+       telescope->setCurrentDeviceName(envDev);
+   }
+   else
+   {
+       // 1. change device name
+       changeAllDeviceNames("LX200 Astro-Physics");
+        telescope->setCurrentDeviceName("LX200 Astro-Physics");
+    }
+
 
    MaxReticleFlashRate = 9;
@@ -415,5 +471,18 @@
  {
   telescope = new LX200Generic();
-  telescope->setCurrentDeviceName("LX200 Generic");
+
+  if (envDev != NULL)
+  {
+      // 1. change device name
+      changeAllDeviceNames(envDev);
+      telescope->setCurrentDeviceName(envDev);
+  }
+  else
+  {
+      // 1. change device name
+      changeAllDeviceNames("LX200 Generic");
+      telescope->setCurrentDeviceName("LX200 Generic");
+  }
+
  }
 
Index: /BAORadio/libindi/libindi/examples/tutorial_four.cpp
===================================================================
--- /BAORadio/libindi/libindi/examples/tutorial_four.cpp	(revision 501)
+++ /BAORadio/libindi/libindi/examples/tutorial_four.cpp	(revision 501)
@@ -0,0 +1,292 @@
+#if 0
+    MyScope - Tutorial Four
+    Demonstration of libindi v0.7 capabilities.
+
+    Copyright (C) 2010 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <memory>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <config.h>
+
+#include "indibase/baseclient.h"
+
+/* INDI Common Library Routines */
+#include "indicom.h"
+
+/* Our driver header */
+#include "tutorial_four.h"
+
+using namespace std;
+
+/* Our telescope auto pointer */
+auto_ptr<MyScope> telescope(0);
+
+const int POLLMS = 1000;				// Period of update, 1 second.
+
+/**************************************************************************************
+** Send client definitions of all properties.
+***************************************************************************************/
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+  return;
+
+ if (telescope.get() == 0)
+ {
+     isInit = 1;
+     telescope.reset(new MyScope());
+ }
+ 
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISGetProperties (const char *dev)
+{
+ ISInit(); 
+ telescope->ISGetProperties(dev);
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewSwitch(dev, name, states, names, n);
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewText(dev, name, texts, names, n);
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewNumber(dev, name, values, names, n);
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+  INDI_UNUSED(dev);
+  INDI_UNUSED(name);
+  INDI_UNUSED(sizes);
+  INDI_UNUSED(blobsizes);
+  INDI_UNUSED(blobs);
+  INDI_UNUSED(formats);
+  INDI_UNUSED(names);
+  INDI_UNUSED(n);
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void ISSnoopDevice (XMLEle *root) 
+{
+  INDI_UNUSED(root);
+}
+
+/**************************************************************************************
+** LX200 Basic constructor
+***************************************************************************************/
+MyScope::MyScope()
+{
+    IDLog("Initilizing from My Scope device...\n");
+
+    init_properties();
+
+ }
+
+/**************************************************************************************
+**
+***************************************************************************************/
+MyScope::~MyScope()
+{
+
+}
+
+/**************************************************************************************
+** Initialize all properties & set default values.
+***************************************************************************************/
+void MyScope::init_properties()
+{
+    // This is the default driver skeleton file location
+    // Convention is: drivername_sk_xml
+    // Default location is /usr/share/indi
+    const char *skelFileName = "/usr/share/indi/tutorial_four_sk.xml";
+    struct stat st;
+
+
+    char *skel = getenv("INDISKEL");
+    if (skel)
+        buildSkeleton(skel);
+    else if (stat(skelFileName,&st) == 0)
+        buildSkeleton(skelFileName);
+    else
+        IDLog("No skeleton file was specified. Set environment variable INDISKEL to the skeleton path and try again.\n");
+
+    // Optional: Add aux controls for configuration, debug & simulation that get added in the Options tab
+    //           of the driver.
+    addAuxControls();
+
+}
+
+/**************************************************************************************
+** Define Basic properties to clients.
+***************************************************************************************/
+void MyScope::ISGetProperties(const char *dev)
+{
+    static int configLoaded = 0;
+
+    // Ask the default driver first to send properties.
+    INDI::DefaultDriver::ISGetProperties(dev);
+
+    // If no configuration is load before, then load it now.
+    if (configLoaded == 0)
+    {
+      loadConfig();
+      configLoaded = 1;
+    }
+
+}
+
+/**************************************************************************************
+** Process Text properties
+***************************************************************************************/
+bool MyScope::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+	// Ignore if not ours 
+        if (strcmp (dev, deviceID))
+            return false;
+
+        return false;
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+bool MyScope::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+	
+	// Ignore if not ours
+        if (strcmp (dev, deviceID))
+            return false;
+
+        INumberVectorProperty *nvp = getNumber(name);
+
+        if (!nvp)
+            return false;
+
+        // Are we updating Slew Accuracy?
+        if (!strcmp(nvp->name, "Slew Accuracy"))
+        {
+            IUUpdateNumber(nvp, values, names, n);
+            nvp->s = IPS_OK;
+            IDSetNumber(nvp, NULL);
+
+            return true;
+        }
+
+        return false;
+}
+
+/**************************************************************************************
+**
+***************************************************************************************/
+bool MyScope::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+	// ignore if not ours //
+        if (strcmp (dev, deviceID))
+            return false;
+
+        if (INDI::DefaultDriver::ISNewSwitch(dev, name, states, names, n) == true)
+            return true;
+
+        ISwitchVectorProperty *svp = getSwitch(name);
+
+        if (!svp)
+            return false;
+
+        // Are we update CONNECTION?
+        if (!strcmp(svp->name, "CONNECTION"))
+        {
+            IUUpdateSwitch(svp, states, names, n);
+            connect_telescope();
+            return true;
+        }
+
+
+}
+
+
+/**************************************************************************************
+**
+***************************************************************************************/
+void MyScope::connect_telescope()
+{
+    ISwitchVectorProperty *svp = getSwitch("CONNECTION");
+
+    ISwitch *sp = IUFindOnSwitch(svp);
+
+    if (!sp)
+        return;
+
+    // Are we connecting?
+    if (!strcmp(sp->name, "CONNECT"))
+    {
+        // Make sure to call setConnected(true) before informing client about successful connection
+        setConnected(true);
+        IDSetSwitch(svp, "Connecting.... telescope is online.");
+        IDLog("Connecting.... telescope is online.\n");
+
+
+    }
+    // Are we disconnecting?
+    else
+    {
+        setConnected(false);
+        IDSetSwitch(svp, "Disconnecting... telescope is offline.");
+        IDLog("Disconnecting... telescope is offline.\n");
+    }
+}
+
+
Index: /BAORadio/libindi/libindi/examples/tutorial_four.h
===================================================================
--- /BAORadio/libindi/libindi/examples/tutorial_four.h	(revision 501)
+++ /BAORadio/libindi/libindi/examples/tutorial_four.h	(revision 501)
@@ -0,0 +1,45 @@
+/*
+    Tutorial Four
+    Copyright (C) 2010 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#ifndef TUTORIAL_FOUR_H
+#define TUTORIAL_FOUR_H
+
+#include "indidevapi.h"
+#include "indicom.h"
+#include "indibase/defaultdriver.h"
+
+class MyScope : public INDI::DefaultDriver
+{
+ public:
+ MyScope();
+ ~MyScope();
+
+ virtual void ISGetProperties (const char *dev);
+ virtual bool ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ virtual bool ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ virtual bool ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+
+private:
+ void init_properties();
+ void connect_telescope();
+
+};
+
+#endif
Index: /BAORadio/libindi/libindi/examples/tutorial_four_sk.xml
===================================================================
--- /BAORadio/libindi/libindi/examples/tutorial_four_sk.xml	(revision 501)
+++ /BAORadio/libindi/libindi/examples/tutorial_four_sk.xml	(revision 501)
@@ -0,0 +1,18 @@
+<INDIDriver>
+<defSwitchVector device="My Device" name="CONNECTION" label="Connection" group="Main Control" state="Idle" perm="rw" rule="OneOfMany" timeout="60">
+    <defSwitch name="CONNECT" label="Connect">
+Off
+    </defSwitch>
+    <defSwitch name="DISCONNECT" label="Disconnect">
+On
+    </defSwitch>
+</defSwitchVector>
+<defNumberVector device="My Device" name="Slew Accuracy" label="" group="Main Control" state="Idle" perm="rw" timeout="0" timestamp="2010-09-02T23:50:48">
+    <defNumber name="SlewRA" label="RA (arcmin)" format="%10.6m" min="0" max="60" step="1">
+3
+    </defNumber>
+    <defNumber name="SlewDEC" label="Dec (arcmin)" format="%10.6m" min="0" max="60" step="1">
+3
+    </defNumber>
+</defNumberVector>
+</INDIDriver>
Index: /BAORadio/libindi/libindi/examples/tutorial_two.c
===================================================================
--- /BAORadio/libindi/libindi/examples/tutorial_two.c	(revision 500)
+++ /BAORadio/libindi/libindi/examples/tutorial_two.c	(revision 501)
@@ -100,6 +100,6 @@
 
 /* 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.*/
-static INumber eqNR[] = {{"RA_REQUEST" ,"RA  H:M:S" , "%10.6m" ,0. , 24., 0., 0., 0, 0, 0},
-			 {"DEC_REQUEST", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0}};
+static INumber eqNR[] = {{"RA" ,"RA  H:M:S" , "%10.6m" ,0. , 24., 0., 0., 0, 0, 0},
+			 {"DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0}};
 static INumberVectorProperty eqNPR = {  mydev, "EQUATORIAL_EOD_COORD_REQUEST", "Equatorial Request",  MAIN_GROUP , IP_RW, 0, IPS_IDLE,  eqNR, NARRAY(eqNR), "", 0};
 
Index: /BAORadio/libindi/libindi/indiapi.h
===================================================================
--- /BAORadio/libindi/libindi/indiapi.h	(revision 500)
+++ /BAORadio/libindi/libindi/indiapi.h	(revision 501)
@@ -48,5 +48,6 @@
 <li><a href="indicom_8h.html">INDI Common Routine Library</a></li>
 <li><a href="lilxml_8h.html">INDI LilXML Library</a></li>
-<li><a href="http://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/cfitsio.html">CFITSIO Library</a></li>
+<li><a href="group__configFunctions.html">Configuration</a></li>
+<li><a href="classINDI_1_1BaseClient.html">Client API</a></li>
 </ul>
 
@@ -74,5 +75,5 @@
 
 /* INDI Library version */
-#define INDI_LIBV	0.6
+#define INDI_LIBV	0.7
 
 /*******************************************************************************
Index: /BAORadio/libindi/libindi/indidevapi.h
===================================================================
--- /BAORadio/libindi/libindi/indidevapi.h	(revision 500)
+++ /BAORadio/libindi/libindi/indidevapi.h	(revision 501)
@@ -302,8 +302,8 @@
     \param snooped_property name of the snooped property in the device.
 */
-extern void IDSnoopDevice (const char *snooped_device, char *snooped_property);
+extern void IDSnoopDevice (const char *snooped_device, const char *snooped_property);
 
 /** \brief Function a Driver calls to control whether they will receive BLOBs from snooped devices.
-    \param snooped_device_name name of the device to snoop.
+    \param snooped_device name of the device to snoop.
     \param bh How drivers handle BLOBs incoming from snooping drivers.
 */
@@ -403,25 +403,41 @@
 /** \brief Find an IText member in a vector text property.
 *
-* \param tp a pointer to a text vector property.
+* \param tvp a pointer to a text vector property.
 * \param name the name of the member to search for.
 * \return a pointer to an IText member on match, or NULL if nothing is found.
 */
-extern IText   *IUFindText  (const ITextVectorProperty *tp, const char *name);
+extern IText   *IUFindText  (const ITextVectorProperty *tvp, const char *name);
 
 /** \brief Find an INumber member in a number text property.
 *
-* \param tp a pointer to a number vector property.
+* \param nvp a pointer to a number vector property.
 * \param name the name of the member to search for.
 * \return a pointer to an INumber member on match, or NULL if nothing is found.
 */
-extern INumber *IUFindNumber(const INumberVectorProperty *tp, const char *name);
+extern INumber *IUFindNumber(const INumberVectorProperty *nvp, const char *name);
 
 /** \brief Find an ISwitch member in a vector switch property.
 *
-* \param tp a pointer to a switch vector property.
+* \param svp a pointer to a switch vector property.
 * \param name the name of the member to search for.
 * \return a pointer to an ISwitch member on match, or NULL if nothing is found.
 */
-extern ISwitch *IUFindSwitch(const ISwitchVectorProperty *tp, const char *name);
+extern ISwitch *IUFindSwitch(const ISwitchVectorProperty *svp, const char *name);
+
+/** \brief Find an ILight member in a vector Light property.
+*
+* \param lvp a pointer to a Light vector property.
+* \param name the name of the member to search for.
+* \return a pointer to an ILight member on match, or NULL if nothing is found.
+*/
+extern ILight *IUFindLight(const ILightVectorProperty *lvp, const char *name);
+
+/** \brief Find an IBLOB member in a vector BLOB property.
+*
+* \param bvp a pointer to a BLOB vector property.
+* \param name the name of the member to search for.
+* \return a pointer to an IBLOB member on match, or NULL if nothing is found.
+*/
+extern IBLOB *IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name);
 
 /** \brief Returns the first ON switch it finds in the vector switch property.
@@ -429,8 +445,8 @@
 *   \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.
 *        
-* \param tp a pointer to a switch vector property.
+* \param sp a pointer to a switch vector property.
 * \return a pointer to the \e first ON ISwitch member if found. If all switches are off, NULL is returned. 
 */
-extern ISwitch *IUFindOnSwitch (const ISwitchVectorProperty *tp);
+extern ISwitch *IUFindOnSwitch (const ISwitchVectorProperty *sp);
 
 /** \brief Reset all switches in a switch vector property to OFF.
@@ -517,4 +533,11 @@
 extern void IUFillText(IText *tp, const char *name, const char * label, const char *initialText);
 
+/** \brief Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
+    \param bp pointer a BLOB property to fill
+    \param name the BLOB name
+    \param label the BLOB label
+    \param format the BLOB format.
+*/
+extern void IUFillBLOB(IBLOB *bp, const char *name, const char * label, const char *format);
 
 /** \brief Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
@@ -573,4 +596,19 @@
 extern 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);
 
+/** \brief Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
+    \param bvp pointer a BLOB vector property to fill
+    \param bp pointer to an array of BLOBs
+    \param nbp the dimension of bp
+    \param dev the device name this vector property belongs to
+    \param name the vector property name
+    \param label the vector property label
+    \param group the vector property group
+    \param p the vector property permission
+    \param timeout vector property timeout in seconds
+    \param s the vector property initial state.
+*/
+extern 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);
+
+
 /** \brief Update a snooped number vector property from the given XML root element.
     \param root XML root elememnt containing the snopped property content
@@ -706,4 +744,54 @@
 #define INDI_UNUSED(x) (void) x
 
+/** \brief Extract dev and name attributes from an XML element.
+    \param root The XML element to be parsed.
+    \param dev pointer to an allocated buffer to save the extracted element device name attribute.
+           The buffer size must be at least MAXINDIDEVICE bytes.
+    \param name pointer to an allocated buffer to save the extracted elemented name attribute.
+           The buffer size must be at least MAXINDINAME bytes.
+    \param msg pointer to an allocated char buffer to store error messages. The minimum buffer size is MAXRBUF.
+    \return 0 if successful, -1 if error is encountered and msg is set.
+*/
+extern int crackDN (XMLEle *root, char **dev, char **name, char msg[]);
+
+/** \brief Extract property state (Idle, OK, Busy, Alert) from the supplied string.
+    \param str A string representation of the state.
+    \param ip Pointer to IPState structure to store the extracted property state.
+    \return 0 if successful, -1 if error is encountered.
+*/
+extern int crackIPState (const char *str, IPState *ip);
+
+/** \brief Extract switch state (On or Off) from the supplied string.
+    \param str A string representation of the switch state.
+    \param ip Pointer to ISState structure to store the extracted switch state.
+    \return 0 if successful, -1 if error is encountered.
+*/
+extern int crackISState (const char *str, ISState *ip);
+
+/** \brief Extract property permission state (RW, RO, WO) from the supplied string.
+    \param str A string representation of the permission state.
+    \param ip Pointer to IPerm structure to store the extracted permission state.
+    \return 0 if successful, -1 if error is encountered.
+*/
+extern int crackIPerm (const char *str, IPerm *ip);
+
+/** \brief Extract switch rule (OneOfMany, OnlyOne..etc) from the supplied string.
+    \param str A string representation of the switch rule.
+    \param ip Pointer to ISRule structure to store the extracted switch rule.
+    \return 0 if successful, -1 if error is encountered.
+*/
+extern int crackISRule (const char *str, ISRule *ip);
+
+/** \return Returns a string representation of the supplied property state. */
+extern const char *pstateStr(IPState s);
+/** \return Returns a string representation of the supplied switch status. */
+extern const char *sstateStr(ISState s);
+/** \return Returns a string representation of the supplied switch rule. */
+extern const char *ruleStr(ISRule r);
+/** \return Returns a string representation of the supplied permission value. */
+extern const char *permStr(IPerm p);
+
+extern void xmlv1(void);
+
 #ifdef __cplusplus
 }
Index: /BAORadio/libindi/libindi/indidriver.c
===================================================================
--- /BAORadio/libindi/libindi/indidriver.c	(revision 501)
+++ /BAORadio/libindi/libindi/indidriver.c	(revision 501)
@@ -0,0 +1,1686 @@
+#if 0
+    INDI
+    Copyright (C) 2003-2006 Elwood C. Downey
+
+                        Updated by Jasem Mutlaq (2003-2010)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "lilxml.h"
+#include "base64.h"
+#include "eventloop.h"
+#include "indidevapi.h"
+#include "indicom.h"
+#include "indidriver.h"
+
+#define MAXRBUF 2048
+
+/* tell Client to delete the property with given name on given device, or
+ * entire device if !name
+ */
+void
+IDDelete (const char *dev, const char *name, const char *fmt, ...)
+{
+	xmlv1();
+	printf ("<delProperty\n  device='%s'\n", dev);
+	if (name)
+	    printf (" name='%s'\n", name);
+	printf ("  timestamp='%s'\n", timestamp());
+	if (fmt) {
+	    va_list ap;
+	    va_start (ap, fmt);
+	    printf ("  message='");
+	    vprintf (fmt, ap);
+	    printf ("'\n");
+	    va_end (ap);
+	}
+	printf ("/>\n");
+	fflush (stdout);
+}
+
+/* tell indiserver we want to snoop on the given device/property.
+ * name ignored if NULL or empty.
+ */
+void
+IDSnoopDevice (const char *snooped_device_name, const char *snooped_property_name)
+{
+	xmlv1();
+	if (snooped_property_name && snooped_property_name[0])
+	    printf ("<getProperties device='%s' name='%s'/>\n",
+				    snooped_device_name, snooped_property_name);
+	else
+	    printf ("<getProperties device='%s'/>\n", snooped_device_name);
+	fflush (stdout);
+}
+
+/* tell indiserver whether we want BLOBs from the given snooped device.
+ * silently ignored if given device is not already registered for snooping.
+ */
+void 
+IDSnoopBLOBs (const char *snooped_device, BLOBHandling bh)
+{
+	const char *how;
+
+	switch (bh) {
+	case B_NEVER: how = "Never"; break;
+	case B_ALSO:  how = "Also";  break;
+	case B_ONLY:  how = "Only";  break;
+	default: return;
+	}
+
+	xmlv1();
+	printf ("<enableBLOB device='%s'>%s</enableBLOB>\n",
+						snooped_device, how);
+	fflush (stdout);
+}
+
+/* "INDI" wrappers to the more generic eventloop facility. */
+
+int
+IEAddCallback (int readfiledes, IE_CBF *fp, void *p)
+{
+	return (addCallback (readfiledes, (CBF*)fp, p));
+}
+
+void
+IERmCallback (int callbackid)
+{
+	rmCallback (callbackid);
+}
+
+int
+IEAddTimer (int millisecs, IE_TCF *fp, void *p)
+{
+	return (addTimer (millisecs, (TCF*)fp, p));
+}
+
+void
+IERmTimer (int timerid)
+{
+	rmTimer (timerid);
+}
+
+int
+IEAddWorkProc (IE_WPF *fp, void *p)
+{
+	return (addWorkProc ((WPF*)fp, p));
+}
+
+void
+IERmWorkProc (int workprocid)
+{
+	rmWorkProc (workprocid);
+}
+
+
+int
+IEDeferLoop (int maxms, int *flagp)
+{
+	return (deferLoop (maxms, flagp));
+}
+
+int
+IEDeferLoop0 (int maxms, int *flagp)
+{
+	return (deferLoop0 (maxms, flagp));
+}
+
+/* Update property switches in accord with states and names. */
+int 
+IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
+{
+ int i=0;
+ ISwitch *sp;
+ char sn[MAXINDINAME];
+
+ /* store On switch name */
+ if (svp->r == ISR_1OFMANY)
+ {
+ 	sp = IUFindOnSwitch(svp);
+ 	if (sp) strncpy(sn, sp->name, MAXINDINAME);
+ 
+	IUResetSwitch(svp);
+ }
+ 
+ for (i = 0; i < n ; i++)
+ {
+   sp = IUFindSwitch(svp, names[i]);
+	 
+   if (!sp)
+   {
+              svp->s = IPS_IDLE;
+	      IDSetSwitch(svp, "Error: %s is not a member of %s property.", names[i], svp->name);
+	      return -1;
+   }
+	 
+   sp->s = states[i]; 
+ }
+ 
+ /* Consistency checks for ISR_1OFMANY after update. */
+ if (svp->r == ISR_1OFMANY)
+ {
+	int t_count=0;
+	for (i=0; i < svp->nsp; i++)
+	{
+		if (svp->sp[i].s == ISS_ON)
+			t_count++;
+	}
+	if (t_count != 1)
+	{
+		IUResetSwitch(svp);
+		sp = IUFindSwitch(svp, sn);
+		if (sp) sp->s = ISS_ON;
+		svp->s = IPS_IDLE;
+		IDSetSwitch(svp, "Error: invalid state switch for property %s. %s.", svp->name, t_count == 0 ? "No switch is on" : "Too many switches are on");
+		return -1;
+	}
+ }
+		
+ return 0;
+
+}
+
+/* Update property numbers in accord with values and names */
+int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
+{
+  int i=0;
+  
+  INumber *np;
+  
+  for (i = 0; i < n; i++)
+  {
+    np = IUFindNumber(nvp, names[i]);
+    if (!np)
+    {
+    	nvp->s = IPS_IDLE;
+	IDSetNumber(nvp, "Error: %s is not a member of %s property.", names[i], nvp->name);
+	return -1;
+    }
+    
+    if (values[i] < np->min || values[i] > np->max)
+    {
+       nvp->s = IPS_IDLE;
+       IDSetNumber(nvp, "Error: Invalid range. Valid range is from %g to %g", np->min, np->max);
+       return -1;
+    }
+      
+  }
+
+  /* First loop checks for error, second loop set all values atomically*/
+  for (i=0; i < n; i++)
+  {
+    np = IUFindNumber(nvp, names[i]);
+    np->value = values[i];
+  }
+
+  return 0;
+
+}
+
+/* Update property text in accord with texts and names */
+int IUUpdateText(ITextVectorProperty *tvp, char * texts[], char *names[], int n)
+{
+  int i=0;
+  
+  IText *tp;
+  
+  for (i = 0; i < n; i++)
+  {
+    tp = IUFindText(tvp, names[i]);
+    if (!tp)
+    {
+    	tvp->s = IPS_IDLE;
+	IDSetText(tvp, "Error: %s is not a member of %s property.", names[i], tvp->name);
+	return -1;
+    }
+  }
+
+  /* First loop checks for error, second loop set all values atomically*/
+  for (i=0; i < n; i++)
+  {
+    tp = IUFindText(tvp, names[i]);
+    IUSaveText(tp, texts[i]);
+  }
+
+  return 0;
+
+}
+
+void IUFillSwitch(ISwitch *sp, const char *name, const char * label, ISState s)
+{
+  strncpy(sp->name, name, MAXINDINAME);
+  strncpy(sp->label, label, MAXINDILABEL);
+  sp->s = s;
+  sp->svp = NULL;
+  sp->aux = NULL;
+}
+
+void IUFillLight(ILight *lp, const char *name, const char * label, IPState s)
+{
+  strncpy(lp->name, name, MAXINDINAME);
+  strncpy(lp->label, label, MAXINDILABEL);
+  lp->s = s;
+  lp->lvp = NULL;
+  lp->aux = NULL;
+}
+
+
+void IUFillNumber(INumber *np, const char *name, const char * label, const char *format, double min, double max, double step, double value)
+{
+
+  strncpy(np->name, name, MAXINDINAME);
+  strncpy(np->label, label, MAXINDILABEL);
+  strncpy(np->format, format, MAXINDIFORMAT);
+  
+  np->min	= min;
+  np->max	= max;
+  np->step	= step;
+  np->value	= value;
+  np->nvp	= NULL;
+  np->aux0	= NULL;
+  np->aux1	= NULL;
+}
+
+void IUFillText(IText *tp, const char *name, const char * label, const char *initialText)
+{
+
+  strncpy(tp->name, name, MAXINDINAME);
+  strncpy(tp->label, label, MAXINDILABEL);
+  tp->text = NULL;
+  tp->tvp  = NULL;
+  tp->aux0 = NULL;
+  tp->aux1 = NULL;
+
+  IUSaveText(tp, initialText);
+
+}
+
+void IUFillBLOB(IBLOB *bp, const char *name, const char * label, const char *format)
+{
+    strncpy(bp->name, name, MAXINDINAME);
+    strncpy(bp->label, label, MAXINDILABEL);
+    strncpy(bp->format, label, MAXINDIBLOBFMT);
+    bp->blob     = 0;
+    bp->bloblen  = 0;
+    bp->size     = 0;
+    bp->bvp      = 0;
+    bp->aux0     = 0;
+    bp->aux1     = 0;
+    bp->aux2     = 0;
+}
+
+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)
+{
+  strncpy(svp->device, dev, MAXINDIDEVICE);
+  strncpy(svp->name, name, MAXINDINAME);
+  strncpy(svp->label, label, MAXINDILABEL);
+  strncpy(svp->group, group, MAXINDIGROUP);
+  strcpy(svp->timestamp, "");
+  
+  svp->p	= p;
+  svp->r	= r;
+  svp->timeout	= timeout;
+  svp->s	= s;
+  svp->sp	= sp;
+  svp->nsp	= nsp;
+}
+
+void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char * dev, const char *name, const char *label, const char *group, IPState s)
+{
+    strncpy(lvp->device, dev, MAXINDIDEVICE);
+    strncpy(lvp->name, name, MAXINDINAME);
+    strncpy(lvp->label, label, MAXINDILABEL);
+    strncpy(lvp->group, group, MAXINDIGROUP);
+    strcpy(lvp->timestamp, "");
+  
+  lvp->s	= s;
+  lvp->lp	= lp;
+  lvp->nlp	= nlp;
+}
+ 
+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)
+{
+  
+ strncpy(nvp->device, dev, MAXINDIDEVICE);
+ strncpy(nvp->name, name, MAXINDINAME);
+ strncpy(nvp->label, label, MAXINDILABEL);
+ strncpy(nvp->group, group, MAXINDIGROUP);
+ strcpy(nvp->timestamp, "");
+  
+  nvp->p	= p;
+  nvp->timeout	= timeout;
+  nvp->s	= s;
+  nvp->np	= np;
+  nvp->nnp	= nnp;
+  
+}
+
+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)
+{
+    strncpy(tvp->device, dev, MAXINDIDEVICE);
+    strncpy(tvp->name, name, MAXINDINAME);
+    strncpy(tvp->label, label, MAXINDILABEL);
+    strncpy(tvp->group, group, MAXINDIGROUP);
+    strcpy(tvp->timestamp, "");
+  
+  tvp->p	= p;
+  tvp->timeout	= timeout;
+  tvp->s	= s;
+  tvp->tp	= tp;
+  tvp->ntp	= ntp;
+
+}
+
+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)
+{
+    strncpy(bvp->device, dev, MAXINDIDEVICE);
+    strncpy(bvp->name, name, MAXINDINAME);
+    strncpy(bvp->label, label, MAXINDILABEL);
+    strncpy(bvp->group, group, MAXINDIGROUP);
+    strcpy(bvp->timestamp, "");
+
+  bvp->p	= p;
+  bvp->timeout	= timeout;
+  bvp->s	= s;
+  bvp->bp	= bp;
+  bvp->nbp	= nbp;
+
+}
+
+/*****************************************************************************
+ * convenience functions for use in your implementation of ISSnoopDevice().
+ */
+
+/* crack the snooped driver setNumberVector or defNumberVector message into
+ * the given INumberVectorProperty.
+ * return 0 if type, device and name match and all members are present, else
+ * return -1
+ */
+int
+IUSnoopNumber (XMLEle *root, INumberVectorProperty *nvp)
+{
+	char *dev, *name;
+	XMLEle *ep;
+	int i;
+
+	/* check and crack type, device, name and state */
+	if (strcmp (tagXMLEle(root)+3, "NumberVector") ||
+					crackDN (root, &dev, &name, NULL) < 0)
+	    return (-1);
+	if (strcmp (dev, nvp->device) || strcmp (name, nvp->name))
+	    return (-1);	/* not this property */
+	(void) crackIPState (findXMLAttValu (root,"state"), &nvp->s);
+
+	/* match each INumber with a oneNumber */
+	for (i = 0; i < nvp->nnp; i++) {
+	    for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+		if (!strcmp (tagXMLEle(ep), "oneNumber") &&
+			!strcmp (nvp->np[i].name, findXMLAttValu(ep, "name"))) {
+		    if (f_scansexa (pcdataXMLEle(ep), &nvp->np[i].value) < 0)
+			return (-1);	/* bad number format */
+		    break;
+		}
+	    }
+	    if (!ep)
+		return (-1);	/* element not found */
+	}
+
+	/* ok */
+	return (0);
+}
+
+/* crack the snooped driver setTextVector or defTextVector message into
+ * the given ITextVectorProperty.
+ * return 0 if type, device and name match and all members are present, else
+ * return -1
+ */
+int
+IUSnoopText (XMLEle *root, ITextVectorProperty *tvp)
+{
+	char *dev, *name;
+	XMLEle *ep;
+	int i;
+
+	/* check and crack type, device, name and state */
+	if (strcmp (tagXMLEle(root)+3, "TextVector") ||
+					crackDN (root, &dev, &name, NULL) < 0)
+	    return (-1);
+	if (strcmp (dev, tvp->device) || strcmp (name, tvp->name))
+	    return (-1);	/* not this property */
+	(void) crackIPState (findXMLAttValu (root,"state"), &tvp->s);
+
+	/* match each IText with a oneText */
+	for (i = 0; i < tvp->ntp; i++) {
+	    for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+		if (!strcmp (tagXMLEle(ep), "oneText") &&
+			!strcmp (tvp->tp[i].name, findXMLAttValu(ep, "name"))) {
+		    IUSaveText (&tvp->tp[i], pcdataXMLEle(ep));
+		    break;
+		}
+	    }
+	    if (!ep)
+		return (-1);	/* element not found */
+	}
+
+	/* ok */
+	return (0);
+}
+
+/* crack the snooped driver setLightVector or defLightVector message into
+ * the given ILightVectorProperty. it is not necessary that all ILight names
+ * be found.
+ * return 0 if type, device and name match, else return -1.
+ */
+int
+IUSnoopLight (XMLEle *root, ILightVectorProperty *lvp)
+{
+	char *dev, *name;
+	XMLEle *ep;
+	int i;
+
+	/* check and crack type, device, name and state */
+	if (strcmp (tagXMLEle(root)+3, "LightVector") ||
+					crackDN (root, &dev, &name, NULL) < 0)
+	    return (-1);
+	if (strcmp (dev, lvp->device) || strcmp (name, lvp->name))
+	    return (-1);	/* not this property */
+
+	(void) crackIPState (findXMLAttValu (root,"state"), &lvp->s);
+
+	/* match each oneLight with one ILight */
+	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+	    if (!strcmp (tagXMLEle(ep), "oneLight")) {
+		const char *name = findXMLAttValu (ep, "name");
+		for (i = 0; i < lvp->nlp; i++) {
+		    if (!strcmp (lvp->lp[i].name, name)) {
+			if (crackIPState(pcdataXMLEle(ep), &lvp->lp[i].s) < 0) {
+			    return (-1);	/* unrecognized state */
+			}
+			break;
+		    }
+		}
+	    }
+	}
+
+	/* ok */
+	return (0);
+}
+
+/* crack the snooped driver setSwitchVector or defSwitchVector message into the
+ * given ISwitchVectorProperty. it is not necessary that all ISwitch names be
+ * found.
+ * return 0 if type, device and name match, else return -1.
+ */
+int
+IUSnoopSwitch (XMLEle *root, ISwitchVectorProperty *svp)
+{
+	char *dev, *name;
+	XMLEle *ep;
+	int i;
+
+	/* check and crack type, device, name and state */
+	if (strcmp (tagXMLEle(root)+3, "SwitchVector") ||
+					crackDN (root, &dev, &name, NULL) < 0)
+	    return (-1);
+	if (strcmp (dev, svp->device) || strcmp (name, svp->name))
+	    return (-1);	/* not this property */
+	(void) crackIPState (findXMLAttValu (root,"state"), &svp->s);
+
+	/* match each oneSwitch with one ISwitch */
+	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+	    if (!strcmp (tagXMLEle(ep), "oneSwitch")) {
+		const char *name = findXMLAttValu (ep, "name");
+		for (i = 0; i < svp->nsp; i++) {
+		    if (!strcmp (svp->sp[i].name, name)) {
+			if (crackISState(pcdataXMLEle(ep), &svp->sp[i].s) < 0) {
+			    return (-1);	/* unrecognized state */
+			}
+			break;
+		    }
+		}
+	    }
+	}
+
+	/* ok */
+	return (0);
+}
+
+/* crack the snooped driver setBLOBVector message into the given
+ * IBLOBVectorProperty. it is not necessary that all IBLOB names be found.
+ * return 0 if type, device and name match, else return -1.
+ * N.B. we assume any existing blob in bvp has been malloced, which we free
+ *   and replace with a newly malloced blob if found.
+ */
+int
+IUSnoopBLOB (XMLEle *root, IBLOBVectorProperty *bvp)
+{
+	char *dev, *name;
+	XMLEle *ep;
+	int i;
+
+	/* check and crack type, device, name and state */
+	if (strcmp (tagXMLEle(root), "setBLOBVector") ||
+					crackDN (root, &dev, &name, NULL) < 0)
+	    return (-1);
+	if (strcmp (dev, bvp->device) || strcmp (name, bvp->name))
+	    return (-1);	/* not this property */
+	(void) crackIPState (findXMLAttValu (root,"state"), &bvp->s);
+
+	/* match each oneBLOB with one IBLOB */
+	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+	    if (!strcmp (tagXMLEle(ep), "oneBLOB")) {
+		const char *name = findXMLAttValu (ep, "name");
+		for (i = 0; i < bvp->nbp; i++) {
+		    IBLOB *bp = &bvp->bp[i];
+		    if (!strcmp (bp->name, name)) {
+			strcpy (bp->format, findXMLAttValu (ep,"format"));
+			bp->size = atof (findXMLAttValu (ep,"size"));
+			bp->bloblen = pcdatalenXMLEle(ep)+1;
+			if (bp->blob)
+			    free (bp->blob);
+			bp->blob = strcpy(malloc(bp->bloblen),pcdataXMLEle(ep));
+			break;
+		    }
+		}
+	    }
+	}
+
+	/* ok */
+	return (0);
+}
+
+/* callback when INDI client message arrives on stdin.
+ * collect and dispatch when see outter element closure.
+ * exit if OS trouble or see incompatable INDI version.
+ * arg is not used.
+ */
+void
+clientMsgCB (int fd, void *arg)
+{
+	char buf[1024], msg[1024], *bp;
+	int nr;
+	arg=arg;
+
+	/* one read */
+	nr = read (fd, buf, sizeof(buf));
+	if (nr < 0) {
+	    fprintf (stderr, "%s: %s\n", me, strerror(errno));
+	    exit(1);
+	}
+	if (nr == 0) {
+	    fprintf (stderr, "%s: EOF\n", me);
+	    exit(1);
+	}
+
+	/* crack and dispatch when complete */
+	for (bp = buf; nr-- > 0; bp++) {
+	    XMLEle *root = readXMLEle (clixml, *bp, msg);
+	    if (root) {
+		if (dispatch (root, msg) < 0)
+		    fprintf (stderr, "%s dispatch error: %s\n", me, msg);
+		delXMLEle (root);
+	    } else if (msg[0])
+		fprintf (stderr, "%s XML error: %s\n", me, msg);
+	}
+
+}
+
+/* crack the given INDI XML element and call driver's IS* entry points as they
+ *   are recognized.
+ * return 0 if ok else -1 with reason in msg[].
+ * N.B. exit if getProperties does not proclaim a compatible version.
+ */
+int
+dispatch (XMLEle *root, char msg[])
+{
+        char *rtag = tagXMLEle(root);
+        XMLEle *ep;
+        int n,i=0;
+
+        if (verbose)
+            prXMLEle (stderr, root, 0);
+
+        /* check tag in surmised decreasing order of likelyhood */
+
+        if (!strcmp (rtag, "newNumberVector")) {
+            static double *doubles;
+            static char **names;
+            static int maxn;
+            char *dev, *name;
+
+            /* pull out device and name */
+            if (crackDN (root, &dev, &name, msg) < 0)
+                return (-1);
+
+            /* seed for reallocs */
+            if (!doubles) {
+                doubles = (double *) malloc (1);
+                names = (char **) malloc (1);
+            }
+
+            /* pull out each name/value pair */
+            for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+                if (strcmp (tagXMLEle(ep), "oneNumber") == 0) {
+                    XMLAtt *na = findXMLAtt (ep, "name");
+                    if (na) {
+                        if (n >= maxn) {
+                            /* grow for this and another */
+                            int newsz = (maxn=n+1)*sizeof(double);
+                            doubles = (double *) realloc(doubles,newsz);
+                            newsz = maxn*sizeof(char *);
+                            names = (char **) realloc (names, newsz);
+                        }
+                        if (f_scansexa (pcdataXMLEle(ep), &doubles[n]) < 0)
+                            IDMessage (dev,"%s: Bad format %s", name,
+                                                            pcdataXMLEle(ep));
+                        else
+                            names[n++] = valuXMLAtt(na);
+                    }
+                }
+            }
+
+            /* insure property is not RO */
+            for (i=0; i < nroCheck; i++)
+            {
+              if (!strcmp(roCheck[i].propName, name))
+              {
+               if (roCheck[i].perm == IP_RO)
+                 return -1;
+              }
+            }
+
+            /* invoke driver if something to do, but not an error if not */
+            if (n > 0)
+                ISNewNumber (dev, name, doubles, names, n);
+            else
+                IDMessage(dev,"%s: newNumberVector with no valid members",name);
+            return (0);
+        }
+
+        if (!strcmp (rtag, "newSwitchVector")) {
+            static ISState *states;
+            static char **names;
+            static int maxn;
+            char *dev, *name;
+            XMLEle *ep;
+
+            /* pull out device and name */
+            if (crackDN (root, &dev, &name, msg) < 0)
+                return (-1);
+
+            /* seed for reallocs */
+            if (!states) {
+                states = (ISState *) malloc (1);
+                names = (char **) malloc (1);
+            }
+
+            /* pull out each name/state pair */
+            for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+                if (strcmp (tagXMLEle(ep), "oneSwitch") == 0) {
+                    XMLAtt *na = findXMLAtt (ep, "name");
+                    if (na) {
+                        if (n >= maxn) {
+                            int newsz = (maxn=n+1)*sizeof(ISState);
+                            states = (ISState *) realloc(states, newsz);
+                            newsz = maxn*sizeof(char *);
+                            names = (char **) realloc (names, newsz);
+                        }
+                        if (strcmp (pcdataXMLEle(ep),"On") == 0) {
+                            states[n] = ISS_ON;
+                            names[n] = valuXMLAtt(na);
+                            n++;
+                        } else if (strcmp (pcdataXMLEle(ep),"Off") == 0) {
+                            states[n] = ISS_OFF;
+                            names[n] = valuXMLAtt(na);
+                            n++;
+                        } else
+                            IDMessage (dev, "%s: must be On or Off: %s", name,
+                                                            pcdataXMLEle(ep));
+                    }
+                }
+            }
+
+            /* insure property is not RO */
+            for (i=0; i < nroCheck; i++)
+            {
+              if (!strcmp(roCheck[i].propName, name))
+              {
+               if (roCheck[i].perm == IP_RO)
+                 return -1;
+              }
+            }
+
+            /* invoke driver if something to do, but not an error if not */
+            if (n > 0)
+                ISNewSwitch (dev, name, states, names, n);
+            else
+                IDMessage(dev,"%s: newSwitchVector with no valid members",name);
+            return (0);
+        }
+
+        if (!strcmp (rtag, "newTextVector")) {
+            static char **texts;
+            static char **names;
+            static int maxn;
+            char *dev, *name;
+
+            /* pull out device and name */
+            if (crackDN (root, &dev, &name, msg) < 0)
+                return (-1);
+
+            /* seed for reallocs */
+            if (!texts) {
+                texts = (char **) malloc (1);
+                names = (char **) malloc (1);
+            }
+
+            /* pull out each name/text pair */
+            for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+                if (strcmp (tagXMLEle(ep), "oneText") == 0) {
+                    XMLAtt *na = findXMLAtt (ep, "name");
+                    if (na) {
+                        if (n >= maxn) {
+                            int newsz = (maxn=n+1)*sizeof(char *);
+                            texts = (char **) realloc (texts, newsz);
+                            names = (char **) realloc (names, newsz);
+                        }
+                        texts[n] = pcdataXMLEle(ep);
+                        names[n] = valuXMLAtt(na);
+                        n++;
+                    }
+                }
+            }
+
+            /* insure property is not RO */
+            for (i=0; i < nroCheck; i++)
+            {
+              if (!strcmp(roCheck[i].propName, name))
+              {
+               if (roCheck[i].perm == IP_RO)
+                 return -1;
+              }
+            }
+
+            /* invoke driver if something to do, but not an error if not */
+            if (n > 0)
+                ISNewText (dev, name, texts, names, n);
+            else
+                IDMessage (dev, "%s: set with no valid members", name);
+            return (0);
+        }
+
+        if (!strcmp (rtag, "newBLOBVector")) {
+            static char **blobs;
+            static char **names;
+            static char **formats;
+            static int *blobsizes;
+            static int *sizes;
+            static int maxn;
+            char *dev, *name;
+            int i;
+
+            /* pull out device and name */
+            if (crackDN (root, &dev, &name, msg) < 0)
+                return (-1);
+
+            /* seed for reallocs */
+            if (!blobs) {
+                blobs = (char **) malloc (1);
+                names = (char **) malloc (1);
+                formats = (char **) malloc (1);
+                blobsizes = (int *) malloc (1);
+                sizes = (int *) malloc (1);
+            }
+
+            /* pull out each name/BLOB pair, decode */
+            for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
+                if (strcmp (tagXMLEle(ep), "oneBLOB") == 0) {
+                    XMLAtt *na = findXMLAtt (ep, "name");
+                    XMLAtt *fa = findXMLAtt (ep, "format");
+                    XMLAtt *sa = findXMLAtt (ep, "size");
+                    if (na && fa && sa) {
+                        if (n >= maxn) {
+                            int newsz = (maxn=n+1)*sizeof(char *);
+                            blobs = (char **) realloc (blobs, newsz);
+                            names = (char **) realloc (names, newsz);
+                            formats = (char **) realloc(formats,newsz);
+                            newsz = maxn*sizeof(int);
+                            sizes = (int *) realloc(sizes,newsz);
+                            blobsizes = (int *) realloc(blobsizes,newsz);
+                        }
+                        blobs[n] = malloc (3*pcdatalenXMLEle(ep)/4);
+                        blobsizes[n] = from64tobits(blobs[n], pcdataXMLEle(ep));
+                        names[n] = valuXMLAtt(na);
+                        formats[n] = valuXMLAtt(fa);
+                        sizes[n] = atoi(valuXMLAtt(sa));
+                        n++;
+                    }
+                }
+            }
+
+            /* invoke driver if something to do, but not an error if not */
+            if (n > 0) {
+                ISNewBLOB (dev, name, sizes, blobsizes, blobs, formats,names,n);
+                for (i = 0; i < n; i++)
+                    free (blobs[i]);
+            } else
+                IDMessage (dev, "%s: newBLOBVector with no valid members",name);
+            return (0);
+        }
+
+        if (!strcmp (rtag, "getProperties")) {
+            XMLAtt *ap;
+            double v;
+
+            /* check version */
+            ap = findXMLAtt (root, "version");
+            if (!ap) {
+                fprintf (stderr, "%s: getProperties missing version\n", me);
+                exit(1);
+            }
+            v = atof (valuXMLAtt(ap));
+            if (v > INDIV) {
+                fprintf (stderr, "%s: client version %g > %g\n", me, v, INDIV);
+                exit(1);
+            }
+
+            /* ok */
+            ap = findXMLAtt (root, "device");
+            ISGetProperties (ap ? valuXMLAtt(ap) : NULL);
+            return (0);
+        }
+
+        /* other commands might be from a snooped device.
+         * we don't know here which devices are being snooped so we send
+         * all remaining valid messages
+         */
+        if (        !strcmp (rtag, "setNumberVector") ||
+                    !strcmp (rtag, "setTextVector") ||
+                    !strcmp (rtag, "setLightVector") ||
+                    !strcmp (rtag, "setSwitchVector") ||
+                    !strcmp (rtag, "setBLOBVector") ||
+                    !strcmp (rtag, "defNumberVector") ||
+                    !strcmp (rtag, "defTextVector") ||
+                    !strcmp (rtag, "defLightVector") ||
+                    !strcmp (rtag, "defSwitchVector") ||
+                    !strcmp (rtag, "defBLOBVector") ||
+                    !strcmp (rtag, "message") ||
+                    !strcmp (rtag, "delProperty")) {
+            ISSnoopDevice (root);
+            return (0);
+        }
+
+        sprintf (msg, "Unknown command: %s", rtag);
+        return(1);
+}
+
+int IUReadConfig(const char *filename, const char *dev, char errmsg[])
+{
+    char configFileName[MAXRBUF], configDefaultFileName[MAXRBUF];
+    char *rname, *rdev;
+    XMLEle *root = NULL, *fproot = NULL;
+    LilXML *lp = newLilXML();
+
+    FILE *fp = NULL;
+
+    if (filename)
+         strncpy(configFileName, filename, MAXRBUF);
+     else
+    {
+        if (getenv("INDICONFIG"))
+            strncpy(configFileName, getenv("INDICONFIG"), MAXRBUF);
+        else
+           snprintf(configFileName, MAXRBUF, "%s/.indi/%s_config.xml", getenv("HOME"), dev);
+
+    }
+
+    fp = fopen(configFileName, "r");
+    if (fp == NULL)
+    {
+         snprintf(errmsg, MAXRBUF, "Unable to read config file. Error loading file %s: %s\n", filename, strerror(errno));
+         return -1;
+    }
+
+    fproot = readXMLFile(fp, lp, errmsg);
+
+    if (fproot == NULL)
+    {
+        snprintf(errmsg, MAXRBUF, "Unable to parse config XML: %s", errmsg);
+        return -1;
+    }
+
+    for (root = nextXMLEle (fproot, 1); root != NULL; root = nextXMLEle (fproot, 0))
+    {
+
+        /* pull out device and name */
+        if (crackDN (root, &rdev, &rname, errmsg) < 0)
+            return -1;
+
+        // It doesn't belong to our device??
+        if (strcmp(dev, rdev))
+            continue;
+
+        dispatch(root, errmsg);
+
+    }
+
+    fclose(fp);
+    delXMLEle(fproot);
+    delXMLEle(root);
+    delLilXML(lp);
+
+    return (0);
+
+}
+
+
+void IUSaveDefaultConfig(const char *source_config, const char *dest_config, const char *dev)
+{
+
+    char configFileName[MAXRBUF], configDefaultFileName[MAXRBUF];
+
+    if (source_config)
+         strncpy(configFileName, source_config, MAXRBUF);
+     else
+    {
+        if (getenv("INDICONFIG"))
+           strncpy(configFileName, getenv("INDICONFIG"), MAXRBUF);
+        else
+           snprintf(configFileName, MAXRBUF, "%s/.indi/%s_config.xml", getenv("HOME"), dev);
+
+    }
+
+     if (dest_config)
+         strncpy(configDefaultFileName, dest_config, MAXRBUF);
+     else if (getenv("INDICONFIG"))
+         snprintf(configDefaultFileName, MAXRBUF, "%s.default", getenv("INDICONFIG"));
+     else
+        snprintf(configDefaultFileName, MAXRBUF, "%s/.indi/%s_config.xml.default", getenv("HOME"), dev);
+
+  // If the default doesn't exist, create it.
+  if (access(configDefaultFileName, F_OK))
+  {
+    FILE *fpin = fopen(configFileName, "r");
+      if(fpin != NULL)
+      {
+        FILE *fpout = fopen(configDefaultFileName, "w");
+        if(fpout != NULL)
+        {
+          int ch = 0;
+          while((ch = getc(fpin)) != EOF)
+            putc(ch, fpout);
+
+          fclose(fpin);
+          fclose(fpout);
+       }
+    }
+  }
+
+}
+
+
+
+
+/* send client a message for a specific device or at large if !dev */
+void
+IDMessage (const char *dev, const char *fmt, ...)
+{
+
+        xmlv1();
+        printf ("<message\n");
+        if (dev)
+            printf (" device='%s'\n", dev);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf ("/>\n");
+        fflush (stdout);
+}
+
+FILE * IUGetConfigFP(const char *filename, const char *dev, char errmsg[])
+{
+    char configFileName[MAXRBUF];
+    char configDir[MAXRBUF];
+    struct stat st;
+    FILE *fp = NULL;
+
+    snprintf(configDir, MAXRBUF, "%s/.indi/", getenv("HOME"));
+
+    if (filename)
+         strncpy(configFileName, filename, MAXRBUF);
+     else
+    {
+        if (getenv("INDICONFIG"))
+            strncpy(configFileName, getenv("INDICONFIG"), MAXRBUF);
+        else
+           snprintf(configFileName, MAXRBUF, "%s%s_config.xml", configDir, dev);
+
+    }
+
+     if(stat(configDir,&st) != 0)
+     {
+         if (mkdir(configDir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH) < 0)
+         {
+             snprintf(errmsg, MAXRBUF, "Unable to create config directory. Error %s: %s\n", configDir, strerror(errno));
+             return NULL;
+         }
+     }
+
+     fp = fopen(configFileName, "w");
+     if (fp == NULL)
+     {
+          snprintf(errmsg, MAXRBUF, "Unable to open config file. Error loading file %s: %s\n", configFileName, strerror(errno));
+          return NULL;
+     }
+
+     return fp;
+}
+
+void IUSaveConfigTag(FILE *fp, int ctag)
+{
+    if (!fp)
+        return;
+
+    /* Opening tag */
+    if (ctag == 0)
+        fprintf(fp, "<INDIDriver>\n");
+    /* Closing tag */
+    else
+       fprintf(fp, "</INDIDriver>\n");
+}
+
+void IUSaveConfigNumber (FILE *fp, const INumberVectorProperty *nvp)
+{
+    int i;
+
+    fprintf (fp, "<newNumberVector device='%s' name='%s'>\n", nvp->device, nvp->name);
+
+    for (i = 0; i < nvp->nnp; i++)
+    {
+        INumber *np = &nvp->np[i];
+        fprintf (fp, "  <oneNumber name='%s'>\n", np->name);
+        fprintf (fp, "      %.20g\n", np->value);
+        fprintf (fp, "  </oneNumber>\n");
+    }
+
+    fprintf (fp, "</newNumberVector>\n");
+}
+
+void IUSaveConfigText (FILE *fp, const ITextVectorProperty *tvp)
+{
+    int i;
+
+    fprintf (fp, "<newTextVector device='%s' name='%s'>\n", tvp->device, tvp->name);
+
+    for (i = 0; i < tvp->ntp; i++)
+    {
+        IText *tp = &tvp->tp[i];
+        fprintf (fp, "  <oneText name='%s'>\n", tp->name);
+        fprintf (fp, "      %s\n", tp->text ? tp->text : "");
+        fprintf (fp, "  </oneText>\n");
+    }
+
+    fprintf (fp, "</newTextVector>\n");
+
+}
+
+void IUSaveConfigSwitch (FILE *fp, const ISwitchVectorProperty *svp)
+{
+    int i;
+
+    fprintf (fp, "<newSwitchVector device='%s' name='%s'>\n", svp->device, svp->name);
+
+    for (i = 0; i < svp->nsp; i++)
+    {
+        ISwitch *sp = &svp->sp[i];
+        fprintf (fp, "  <oneSwitch name='%s'>\n", sp->name);
+        fprintf (fp, "      %s\n", sstateStr(sp->s));
+        fprintf (fp, "  </oneSwitch>\n");
+    }
+
+    fprintf (fp, "</newSwitchVector>\n");
+
+}
+
+void IUSaveConfigBLOB (FILE *fp, const IBLOBVectorProperty *bvp)
+{
+    int i;
+
+    fprintf (fp, "<newBLOBVector device='%s' name='%s'>\n", bvp->device, bvp->name);
+
+    for (i = 0; i < bvp->nbp; i++)
+    {
+        IBLOB *bp = &bvp->bp[i];
+        unsigned char *encblob;
+        int j, l;
+
+        fprintf (fp, "  <oneBLOB\n");
+        fprintf (fp, "    name='%s'\n", bp->name);
+        fprintf (fp, "    size='%d'\n", bp->size);
+        fprintf (fp, "    format='%s'>\n", bp->format);
+
+        encblob = malloc (4*bp->bloblen/3+4);
+        l = to64frombits(encblob, bp->blob, bp->bloblen);
+        for (j = 0; j < l; j += 72)
+            fprintf (fp, "%.72s\n", encblob+j);
+        free (encblob);
+
+        fprintf (fp, "  </oneBLOB>\n");
+    }
+
+    fprintf (fp, "</newBLOBVector>\n");
+
+}
+
+/* tell client to create a text vector property */
+void
+IDDefText (const ITextVectorProperty *tvp, const char *fmt, ...)
+{
+        int i;
+        ROSC *SC;
+
+        xmlv1();
+        printf ("<defTextVector\n");
+        printf ("  device='%s'\n", tvp->device);
+        printf ("  name='%s'\n", tvp->name);
+        printf ("  label='%s'\n", tvp->label);
+        printf ("  group='%s'\n", tvp->group);
+        printf ("  state='%s'\n", pstateStr(tvp->s));
+        printf ("  perm='%s'\n", permStr(tvp->p));
+        printf ("  timeout='%g'\n", tvp->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < tvp->ntp; i++) {
+            IText *tp = &tvp->tp[i];
+            printf ("  <defText\n");
+            printf ("    name='%s'\n", tp->name);
+            printf ("    label='%s'>\n", tp->label);
+            printf ("      %s\n", tp->text ? tp->text : "");
+            printf ("  </defText>\n");
+        }
+
+        printf ("</defTextVector>\n");
+
+        if (!isPropDefined(tvp->name))
+        {
+                /* Add this property to insure proper sanity check */
+                roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+                                : (ROSC *) malloc  ( sizeof(ROSC));
+                SC      = &roCheck[nroCheck++];
+
+                strcpy(SC->propName, tvp->name);
+                SC->perm = tvp->p;
+        }
+
+        fflush (stdout);
+}
+
+/* tell client to create a new numeric vector property */
+void
+IDDefNumber (const INumberVectorProperty *n, const char *fmt, ...)
+{
+        int i;
+        ROSC *SC;
+
+        xmlv1();
+        printf ("<defNumberVector\n");
+        printf ("  device='%s'\n", n->device);
+        printf ("  name='%s'\n", n->name);
+        printf ("  label='%s'\n", n->label);
+        printf ("  group='%s'\n", n->group);
+        printf ("  state='%s'\n", pstateStr(n->s));
+        printf ("  perm='%s'\n", permStr(n->p));
+        printf ("  timeout='%g'\n", n->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+
+
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+
+        for (i = 0; i < n->nnp; i++) {
+
+            INumber *np = &n->np[i];
+
+            printf ("  <defNumber\n");
+            printf ("    name='%s'\n", np->name);
+            printf ("    label='%s'\n", np->label);
+            printf ("    format='%s'\n", np->format);
+            printf ("    min='%.20g'\n", np->min);
+            printf ("    max='%.20g'\n", np->max);
+            printf ("    step='%.20g'>\n", np->step);
+            printf ("      %.20g\n", np->value);
+
+            printf ("  </defNumber>\n");
+        }
+
+        printf ("</defNumberVector>\n");
+
+        if (!isPropDefined(n->name))
+        {
+                /* Add this property to insure proper sanity check */
+                roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+                                : (ROSC *) malloc  ( sizeof(ROSC));
+                SC      = &roCheck[nroCheck++];
+
+                strcpy(SC->propName, n->name);
+                SC->perm = n->p;
+
+        }
+
+        fflush (stdout);
+}
+
+/* tell client to create a new switch vector property */
+void
+IDDefSwitch (const ISwitchVectorProperty *s, const char *fmt, ...)
+
+{
+        int i;
+        ROSC *SC;
+
+        xmlv1();
+        printf ("<defSwitchVector\n");
+        printf ("  device='%s'\n", s->device);
+        printf ("  name='%s'\n", s->name);
+        printf ("  label='%s'\n", s->label);
+        printf ("  group='%s'\n", s->group);
+        printf ("  state='%s'\n", pstateStr(s->s));
+        printf ("  perm='%s'\n", permStr(s->p));
+        printf ("  rule='%s'\n", ruleStr (s->r));
+        printf ("  timeout='%g'\n", s->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < s->nsp; i++) {
+            ISwitch *sp = &s->sp[i];
+            printf ("  <defSwitch\n");
+            printf ("    name='%s'\n", sp->name);
+            printf ("    label='%s'>\n", sp->label);
+            printf ("      %s\n", sstateStr(sp->s));
+            printf ("  </defSwitch>\n");
+        }
+
+        printf ("</defSwitchVector>\n");
+
+        if (!isPropDefined(s->name))
+        {
+                /* Add this property to insure proper sanity check */
+                roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+                                : (ROSC *) malloc  ( sizeof(ROSC));
+                SC      = &roCheck[nroCheck++];
+
+                strcpy(SC->propName, s->name);
+                SC->perm = s->p;
+        }
+
+        fflush (stdout);
+}
+
+/* tell client to create a new lights vector property */
+void
+IDDefLight (const ILightVectorProperty *lvp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<defLightVector\n");
+        printf ("  device='%s'\n", lvp->device);
+        printf ("  name='%s'\n", lvp->name);
+        printf ("  label='%s'\n", lvp->label);
+        printf ("  group='%s'\n", lvp->group);
+        printf ("  state='%s'\n", pstateStr(lvp->s));
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < lvp->nlp; i++) {
+            ILight *lp = &lvp->lp[i];
+            printf ("  <defLight\n");
+            printf ("    name='%s'\n", lp->name);
+            printf ("    label='%s'>\n", lp->label);
+            printf ("      %s\n", pstateStr(lp->s));
+            printf ("  </defLight>\n");
+        }
+
+        printf ("</defLightVector>\n");
+        fflush (stdout);
+}
+
+/* tell client to create a new BLOB vector property */
+void
+IDDefBLOB (const IBLOBVectorProperty *b, const char *fmt, ...)
+{
+  int i;
+  ROSC *SC;
+
+        xmlv1();
+        printf ("<defBLOBVector\n");
+        printf ("  device='%s'\n", b->device);
+        printf ("  name='%s'\n", b->name);
+        printf ("  label='%s'\n", b->label);
+        printf ("  group='%s'\n", b->group);
+        printf ("  state='%s'\n", pstateStr(b->s));
+        printf ("  perm='%s'\n", permStr(b->p));
+        printf ("  timeout='%g'\n", b->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+  for (i = 0; i < b->nbp; i++) {
+    IBLOB *bp = &b->bp[i];
+    printf ("  <defBLOB\n");
+    printf ("    name='%s'\n", bp->name);
+    printf ("    label='%s'\n", bp->label);
+    printf ("  />\n");
+  }
+
+        printf ("</defBLOBVector>\n");
+
+        if (!isPropDefined(b->name))
+        {
+                /* Add this property to insure proper sanity check */
+                roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+                                : (ROSC *) malloc  ( sizeof(ROSC));
+                SC      = &roCheck[nroCheck++];
+
+                strcpy(SC->propName, b->name);
+                SC->perm = b->p;
+        }
+
+        fflush (stdout);
+}
+
+/* tell client to update an existing text vector property */
+void
+IDSetText (const ITextVectorProperty *tvp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<setTextVector\n");
+        printf ("  device='%s'\n", tvp->device);
+        printf ("  name='%s'\n", tvp->name);
+        printf ("  state='%s'\n", pstateStr(tvp->s));
+        printf ("  timeout='%g'\n", tvp->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < tvp->ntp; i++) {
+            IText *tp = &tvp->tp[i];
+            printf ("  <oneText name='%s'>\n", tp->name);
+            printf ("      %s\n", tp->text ? tp->text : "");
+            printf ("  </oneText>\n");
+        }
+
+        printf ("</setTextVector>\n");
+        fflush (stdout);
+}
+
+/* tell client to update an existing numeric vector property */
+void
+IDSetNumber (const INumberVectorProperty *nvp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<setNumberVector\n");
+        printf ("  device='%s'\n", nvp->device);
+        printf ("  name='%s'\n", nvp->name);
+        printf ("  state='%s'\n", pstateStr(nvp->s));
+        printf ("  timeout='%g'\n", nvp->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < nvp->nnp; i++) {
+            INumber *np = &nvp->np[i];
+            printf ("  <oneNumber name='%s'>\n", np->name);
+            printf ("      %.20g\n", np->value);
+            printf ("  </oneNumber>\n");
+        }
+
+        printf ("</setNumberVector>\n");
+        fflush (stdout);
+}
+
+/* tell client to update an existing switch vector property */
+void
+IDSetSwitch (const ISwitchVectorProperty *svp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<setSwitchVector\n");
+        printf ("  device='%s'\n", svp->device);
+        printf ("  name='%s'\n", svp->name);
+        printf ("  state='%s'\n", pstateStr(svp->s));
+        printf ("  timeout='%g'\n", svp->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < svp->nsp; i++) {
+            ISwitch *sp = &svp->sp[i];
+            printf ("  <oneSwitch name='%s'>\n", sp->name);
+            printf ("      %s\n", sstateStr(sp->s));
+            printf ("  </oneSwitch>\n");
+        }
+
+        printf ("</setSwitchVector>\n");
+        fflush (stdout);
+}
+
+/* tell client to update an existing lights vector property */
+void
+IDSetLight (const ILightVectorProperty *lvp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<setLightVector\n");
+        printf ("  device='%s'\n", lvp->device);
+        printf ("  name='%s'\n", lvp->name);
+        printf ("  state='%s'\n", pstateStr(lvp->s));
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < lvp->nlp; i++) {
+            ILight *lp = &lvp->lp[i];
+            printf ("  <oneLight name='%s'>\n", lp->name);
+            printf ("      %s\n", pstateStr(lp->s));
+            printf ("  </oneLight>\n");
+        }
+
+        printf ("</setLightVector>\n");
+        fflush (stdout);
+}
+
+/* tell client to update an existing BLOB vector property */
+void
+IDSetBLOB (const IBLOBVectorProperty *bvp, const char *fmt, ...)
+{
+        int i;
+
+        xmlv1();
+        printf ("<setBLOBVector\n");
+        printf ("  device='%s'\n", bvp->device);
+        printf ("  name='%s'\n", bvp->name);
+        printf ("  state='%s'\n", pstateStr(bvp->s));
+        printf ("  timeout='%g'\n", bvp->timeout);
+        printf ("  timestamp='%s'\n", timestamp());
+        if (fmt) {
+            va_list ap;
+            va_start (ap, fmt);
+            printf ("  message='");
+            vprintf (fmt, ap);
+            printf ("'\n");
+            va_end (ap);
+        }
+        printf (">\n");
+
+        for (i = 0; i < bvp->nbp; i++) {
+            IBLOB *bp = &bvp->bp[i];
+            unsigned char *encblob;
+            int j, l;
+
+            printf ("  <oneBLOB\n");
+            printf ("    name='%s'\n", bp->name);
+            printf ("    size='%d'\n", bp->size);
+            printf ("    format='%s'>\n", bp->format);
+
+            encblob = malloc (4*bp->bloblen/3+4);
+            l = to64frombits(encblob, bp->blob, bp->bloblen);
+            for (j = 0; j < l; j += 72)
+                printf ("%.72s\n", encblob+j);
+            free (encblob);
+
+            printf ("  </oneBLOB>\n");
+        }
+
+  printf ("</setBLOBVector>\n");
+  fflush (stdout);
+}
+
+/* tell client to update min/max elements of an existing number vector property */
+void IUUpdateMinMax(const INumberVectorProperty *nvp)
+{
+  int i;
+
+  xmlv1();
+  printf ("<setNumberVector\n");
+  printf ("  device='%s'\n", nvp->device);
+  printf ("  name='%s'\n", nvp->name);
+  printf ("  state='%s'\n", pstateStr(nvp->s));
+  printf ("  timeout='%g'\n", nvp->timeout);
+  printf ("  timestamp='%s'\n", timestamp());
+  printf (">\n");
+
+  for (i = 0; i < nvp->nnp; i++) {
+    INumber *np = &nvp->np[i];
+    printf ("  <oneNumber name='%s'\n", np->name);
+    printf ("    min='%g'\n", np->min);
+    printf ("    max='%g'\n", np->max);
+    printf ("    step='%g'\n", np->step);
+    printf(">\n");
+    printf ("      %g\n", np->value);
+    printf ("  </oneNumber>\n");
+  }
+
+  printf ("</setNumberVector>\n");
+  fflush (stdout);
+}
+
+/* Return 1 is property is already cached, 0 otherwise */
+int isPropDefined(const char *property_name)
+{
+  int i=0;
+
+  for (i=0; i < nroCheck; i++)
+    if (!strcmp(property_name, roCheck[i].propName))
+        return 1;
+
+  return 0;
+
+}
+
+
Index: /BAORadio/libindi/libindi/indidriver.h
===================================================================
--- /BAORadio/libindi/libindi/indidriver.h	(revision 501)
+++ /BAORadio/libindi/libindi/indidriver.h	(revision 501)
@@ -0,0 +1,150 @@
+#if 0
+    INDI
+    Copyright (C) 2003-2006 Elwood C. Downey
+
+                        Updated by Jasem Mutlaq (2003-2010)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+#endif
+
+#ifndef INDIDRIVER_H
+#define INDIDRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* insure RO properties are never modified. RO Sanity Check */
+typedef struct
+{
+ char propName[MAXINDINAME];
+ IPerm perm;
+} ROSC;
+
+extern ROSC *roCheck;
+extern int nroCheck;			/* # of elements in roCheck */
+extern int verbose;			/* chatty */
+extern char *me;				/* a.out name */
+extern LilXML *clixml;			/* XML parser context */
+
+extern int dispatch (XMLEle *root, char msg[]);
+extern void clientMsgCB(int fd, void *arg);
+
+/**
+ * \defgroup configFunctions Configuration Functions: Functions drivers call to save and load configuraion options.
+
+<p>Drivers can save properties states and values in an XML configuration file. The following functions take an optinal filename
+parameter which specifies the full path of the configuration file. If the filename is set to NULL, the configuration file
+is locally stored in ~/.indi. By default, two configuration files may exist for each driver:</p>
+<ul>
+<li>Last Saved Configuration: ~/.indi/driver_name_config.xml</li>
+<li>Default Configuration: ~/.indi/driver_name_config.xml.default</li>
+</ul>
+
+<p>libindi stores the configuration parameters enclosed in newXXX commands. Therefore, if a configuration file is loaded,
+the driver property gets updated as if a client is setting these values. This is important to note since some configuration
+options may only available when the device is powered up or is in a particular state.</p>
+
+<p>If no filename is supplied, each function will try to create the configuration files in the following order:</p>
+<ol>
+<li>INDICONFIG environment variable: The functions checks if the envrionment variable is defined, and if so, it shall
+be used as the configuration filename</li>
+<li>Generate filename: If the <i>device_name</i> is supplied, the function will attempt to set the configuration filename to ~/.indi/device_name_config.xml</li>
+</ol>
+\note Drivers subclassing INDI::DefaultDevice do not need to call the configuration functions directly as it is handled internally by the class.
+\version libindi 0.7+
+*/
+
+
+/*@{*/
+
+/** \brief Open a configuration file for writing and return a configuration file FILE pointer.
+    \param filename full path of the configuration file. If set, the function will attempt to open it for writing.
+           If set to NULL, it will attempt to generate the filename as described in the <b>Detailed Description</b> introduction and then open it for writing.
+    \param dev device name. This is used if the filename parameter is NULL, and INDICONFIG environment variable is not set as described in the <b>Detailed Description</b> introduction.
+    \param errmsg In case of errors, store the error message in this buffer. The size of the buffer must be at least MAXRBUF.
+    \return pointer to FILE if configuration file is opened successful, otherwise NULL and errmsg is set.
+*/
+extern FILE * IUGetConfigFP(const char *filename, const char *dev, char errmsg[]);
+
+/** \brief Loads and processes a configuration file.
+
+  Once a configuration file is successful loaded, the function will iterate over the enclosed newXXX commands, and dispatches
+  each command to the driver. Subsequently, the driver receives the updated property value in the driver's ISNewXXX functions.
+  The driver may call this function at any time. However, it is usually called either on driver startup or on device power up.
+
+    \param filename full path of the configuration file. If set, the function will attempt to load the file.
+           If set to NULL, it will attempt to generate the filename as described in the <b>Detailed Description</b> introduction and then load it.
+    \param dev device name. This is used if the filename parameter is NULL, and INDICONFIG environment variable is not set as described in the <b>Detailed Description</b> introduction.
+    \param errmsg In case of errors, store the error message in this buffer. The size of the buffer must be at least MAXRBUF.
+    \return 0 on successful, -1 if there is an error and errmsg is set.
+*/
+extern int IUReadConfig(const char *filename, const char *dev, char errmsg[]);
+
+/** \brief Copies an existing configuration file into a default configuration file.
+
+  If no <i>default</i> configuration file for the supplied <i>dev</i> exists, it gets created and its contentes copied from an exiting source configuration file.
+  Usually, when the user saves the configuration file of a driver for the first time, IUSaveDefaultConfig is called to create the default
+  configuration file. If the default configuration file already exists, the function performs no action and returns.
+    \param source_config full path of the source configuration file to read. If set, the function will attempt to load the file.
+           If set to NULL, it will attempt to generate the filename as described in the <b>Detailed Description</b> introduction and then load it.
+    \param dest_config full path of the destination default configuration file to write. If set, the function will attempt to load the file.
+           If set to NULL, it will attempt to generate the filename as described in the <b>Detailed Description</b> introduction and then load it.
+           If the file already exists, the function returns. If the file doesn't exist, it gets created and its contents copied from the source_config file.
+    \param dev device name. This is used if either the source_config or desg_config are NULL, and INDICONFIG environment variable is not set as described in the <b>Detailed Description</b> introduction.
+*/
+extern void IUSaveDefaultConfig(const char *source_config, const char *dest_config, const char *dev);
+
+/** \brief Add opening or closing tag to a configuration file.
+
+  A configuration file root XML element is @<INDIDriver>@. This functions add @<INDIDriver>@ or @</INDIDriver>@ as required.
+    \param fp file pointer to a configuration file.
+    \param ctag If 0, @<INDIDriver>@ is appened to the configuration file, otherwise @</INDIDriver>@ is appeneded and the <i>fp</i> is closed.
+*/
+extern void IUSaveConfigTag(FILE *fp, int ctag);
+
+/** \brief Add a number vector property value to the configuration file
+    \param fp file pointer to a configuration file.
+    \param nvp pointer to a number vector property.
+*/
+extern void IUSaveConfigNumber (FILE *fp, const INumberVectorProperty *nvp);
+
+/** \brief Add a text vector property value to the configuration file
+    \param fp file pointer to a configuration file.
+    \param tvp pointer to a text vector property.
+*/
+extern void IUSaveConfigText (FILE *fp, const ITextVectorProperty *tvp);
+
+/** \brief Add a switch vector property value to the configuration file
+    \param fp file pointer to a configuration file.
+    \param svp pointer to a switch vector property.
+*/
+extern void IUSaveConfigSwitch (FILE *fp, const ISwitchVectorProperty *svp);
+
+/** \brief Add a BLOB vector property value to the configuration file
+    \param fp file pointer to a configuration file.
+    \param bvp pointer to a BLOB vector property.
+    \note If the BLOB size is large, this function will block until the BLOB contents are written to the file.
+*/
+extern void IUSaveConfigBLOB (FILE *fp, const IBLOBVectorProperty *bvp);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /BAORadio/libindi/libindi/indidrivermain.c
===================================================================
--- /BAORadio/libindi/libindi/indidrivermain.c	(revision 500)
+++ /BAORadio/libindi/libindi/indidrivermain.c	(revision 501)
@@ -3,5 +3,5 @@
     Copyright (C) 2003-2006 Elwood C. Downey
 
-			Modified by Jasem Mutlaq (2003-2006)
+                        Updated by Jasem Mutlaq (2003-2010)
 
     This library is free software; you can redistribute it and/or
@@ -46,32 +46,16 @@
 #include "indidevapi.h"
 #include "indicom.h"
+#include "indidriver.h"
 
-static void usage(void);
-static void clientMsgCB(int fd, void *arg);
-static int dispatch (XMLEle *root, char msg[]);
-static int crackDN (XMLEle *root, char **dev, char **name, char msg[]);
-static int isPropDefined(const char *property_name);
-static int crackIPState (const char *str, IPState *ip);
-static int crackISState (const char *str, ISState *ip);
-static void xmlv1(void);
-const char *pstateStr(IPState s);
-const char *sstateStr(ISState s);
-const char *ruleStr(ISRule r);
-const char *permStr(IPerm p);
+#define MAXRBUF 2048
 
+ROSC *roCheck;
+int nroCheck;			/* # of elements in roCheck */
 
-static int nroCheck;			/* # of elements in roCheck */
-static int verbose;			/* chatty */
+int verbose;			/* chatty */
 char *me;				/* a.out name */
-static LilXML *clixml;			/* XML parser context */
+LilXML *clixml;			/* XML parser context */
 
-/* insure RO properties are never modified. RO Sanity Check */
-typedef struct
-{
-  char propName[MAXINDINAME];
-  IPerm perm;
-} ROSC;
-
-static ROSC *roCheck;
+static void  usage(void);
 
 int
@@ -109,7 +93,4 @@
 	clixml =  newLilXML();
 	addCallback (0, clientMsgCB, NULL);
-	
-	nroCheck = 0;
-	roCheck = NULL;
 
 	/* service client */
@@ -121,1570 +102,13 @@
 }
 
-/* Return 1 is property is already cached, 0 otherwise */
-static int isPropDefined(const char *property_name)
+/* print usage message and exit (1) */
+static void  usage(void)
 {
-  int i=0;
-  
-  for (i=0; i < nroCheck; i++)
-    if (!strcmp(property_name, roCheck[i].propName))
-	return 1;
+            fprintf (stderr, "Usage: %s [options]\n", me);
+            fprintf (stderr, "Purpose: INDI Device driver framework.\n");
+            fprintf (stderr, "Options:\n");
+            fprintf (stderr, " -v    : more verbose to stderr\n");
 
-  return 0;
-
+            exit (1);
 }
 
-/* functions we define that drivers may call */
-
-/* tell client to create a text vector property */
-void
-IDDefText (const ITextVectorProperty *tvp, const char *fmt, ...)
-{
-	int i;
-	ROSC *SC;
-
-	xmlv1();
-	printf ("<defTextVector\n");
-	printf ("  device='%s'\n", tvp->device);
-	printf ("  name='%s'\n", tvp->name);
-	printf ("  label='%s'\n", tvp->label);
-	printf ("  group='%s'\n", tvp->group);
-	printf ("  state='%s'\n", pstateStr(tvp->s));
-	printf ("  perm='%s'\n", permStr(tvp->p));
-	printf ("  timeout='%g'\n", tvp->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < tvp->ntp; i++) {
-	    IText *tp = &tvp->tp[i];
-	    printf ("  <defText\n");
-	    printf ("    name='%s'\n", tp->name);
-	    printf ("    label='%s'>\n", tp->label);
-	    printf ("      %s\n", tp->text ? tp->text : "");
-	    printf ("  </defText>\n");
-	}
-
-	printf ("</defTextVector>\n");
-
-	if (!isPropDefined(tvp->name))
-	{	
-		/* Add this property to insure proper sanity check */
-		roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
-	                  	: (ROSC *) malloc  ( sizeof(ROSC));
-		SC      = &roCheck[nroCheck++];
-	
-		strcpy(SC->propName, tvp->name);
-		SC->perm = tvp->p;
-	}
-	
-	fflush (stdout);
-}
-
-/* tell client to create a new numeric vector property */
-void
-IDDefNumber (const INumberVectorProperty *n, const char *fmt, ...)
-{
-	int i;
-	ROSC *SC;
-
-	xmlv1();
-	printf ("<defNumberVector\n");
-	printf ("  device='%s'\n", n->device);
-	printf ("  name='%s'\n", n->name);
-	printf ("  label='%s'\n", n->label);
-	printf ("  group='%s'\n", n->group);
-	printf ("  state='%s'\n", pstateStr(n->s));
-	printf ("  perm='%s'\n", permStr(n->p));
-	printf ("  timeout='%g'\n", n->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < n->nnp; i++) {
-	    INumber *np = &n->np[i];
-	    printf ("  <defNumber\n");
-	    printf ("    name='%s'\n", np->name);
-	    printf ("    label='%s'\n", np->label);
-	    printf ("    format='%s'\n", np->format);
-	    printf ("    min='%.20g'\n", np->min);
-	    printf ("    max='%.20g'\n", np->max);
-	    printf ("    step='%.20g'>\n", np->step);
-	    printf ("      %.20g\n", np->value);
-	    printf ("  </defNumber>\n");
-	}
-
-	printf ("</defNumberVector>\n");
-	
-	if (!isPropDefined(n->name))
-	{	
-		/* Add this property to insure proper sanity check */
-		roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
-	                  	: (ROSC *) malloc  ( sizeof(ROSC));
-		SC      = &roCheck[nroCheck++];
-	
-		strcpy(SC->propName, n->name);
-		SC->perm = n->p;
-
-	}
-	
-	fflush (stdout);
-}
-
-/* tell client to create a new switch vector property */
-void
-IDDefSwitch (const ISwitchVectorProperty *s, const char *fmt, ...)
-
-{
-	int i;
-	ROSC *SC;
-
-	xmlv1();
-	printf ("<defSwitchVector\n");
-	printf ("  device='%s'\n", s->device);
-	printf ("  name='%s'\n", s->name);
-	printf ("  label='%s'\n", s->label);
-	printf ("  group='%s'\n", s->group);
-	printf ("  state='%s'\n", pstateStr(s->s));
-	printf ("  perm='%s'\n", permStr(s->p));
-	printf ("  rule='%s'\n", ruleStr (s->r));
-	printf ("  timeout='%g'\n", s->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < s->nsp; i++) {
-	    ISwitch *sp = &s->sp[i];
-	    printf ("  <defSwitch\n");
-	    printf ("    name='%s'\n", sp->name);
-	    printf ("    label='%s'>\n", sp->label);
-	    printf ("      %s\n", sstateStr(sp->s));
-	    printf ("  </defSwitch>\n");
-	}
-
-	printf ("</defSwitchVector>\n");
-	
-	if (!isPropDefined(s->name))
-	{	
-		/* Add this property to insure proper sanity check */
-		roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
-	                  	: (ROSC *) malloc  ( sizeof(ROSC));
-		SC      = &roCheck[nroCheck++];
-	
-		strcpy(SC->propName, s->name);
-		SC->perm = s->p;
-	}
-	
-	fflush (stdout);
-}
-
-/* tell client to create a new lights vector property */
-void
-IDDefLight (const ILightVectorProperty *lvp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<defLightVector\n");
-	printf ("  device='%s'\n", lvp->device);
-	printf ("  name='%s'\n", lvp->name);
-	printf ("  label='%s'\n", lvp->label);
-	printf ("  group='%s'\n", lvp->group);
-	printf ("  state='%s'\n", pstateStr(lvp->s));
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < lvp->nlp; i++) {
-	    ILight *lp = &lvp->lp[i];
-	    printf ("  <defLight\n");
-	    printf ("    name='%s'\n", lp->name);
-	    printf ("    label='%s'>\n", lp->label);
-	    printf ("      %s\n", pstateStr(lp->s));
-	    printf ("  </defLight>\n");
-	}
-
-	printf ("</defLightVector>\n");
-	fflush (stdout);
-}
-
-/* tell client to create a new BLOB vector property */
-void
-IDDefBLOB (const IBLOBVectorProperty *b, const char *fmt, ...)
-{
-  int i;
-  ROSC *SC;
-
-	xmlv1();
-	printf ("<defBLOBVector\n");
-	printf ("  device='%s'\n", b->device);
-	printf ("  name='%s'\n", b->name);
-	printf ("  label='%s'\n", b->label);
-	printf ("  group='%s'\n", b->group);
-	printf ("  state='%s'\n", pstateStr(b->s));
-	printf ("  perm='%s'\n", permStr(b->p));
-	printf ("  timeout='%g'\n", b->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-  for (i = 0; i < b->nbp; i++) {
-    IBLOB *bp = &b->bp[i];
-    printf ("  <defBLOB\n");
-    printf ("    name='%s'\n", bp->name);
-    printf ("    label='%s'\n", bp->label);
-    printf ("  />\n");
-  }
-
-	printf ("</defBLOBVector>\n");
-
-	if (!isPropDefined(b->name))
-	{	
-		/* Add this property to insure proper sanity check */
-		roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
-	                  	: (ROSC *) malloc  ( sizeof(ROSC));
-		SC      = &roCheck[nroCheck++];
-	
-		strcpy(SC->propName, b->name);
-		SC->perm = b->p;
-	}
-
-	fflush (stdout);
-}
-
-/* tell client to update an existing text vector property */
-void
-IDSetText (const ITextVectorProperty *tvp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<setTextVector\n");
-	printf ("  device='%s'\n", tvp->device);
-	printf ("  name='%s'\n", tvp->name);
-	printf ("  state='%s'\n", pstateStr(tvp->s));
-	printf ("  timeout='%g'\n", tvp->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < tvp->ntp; i++) {
-	    IText *tp = &tvp->tp[i];
-	    printf ("  <oneText name='%s'>\n", tp->name);
-	    printf ("      %s\n", tp->text ? tp->text : "");
-	    printf ("  </oneText>\n");
-	}
-
-	printf ("</setTextVector>\n");
-	fflush (stdout);
-}
-
-/* tell client to update an existing numeric vector property */
-void
-IDSetNumber (const INumberVectorProperty *nvp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<setNumberVector\n");
-	printf ("  device='%s'\n", nvp->device);
-	printf ("  name='%s'\n", nvp->name);
-	printf ("  state='%s'\n", pstateStr(nvp->s));
-	printf ("  timeout='%g'\n", nvp->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < nvp->nnp; i++) {
-	    INumber *np = &nvp->np[i];
-	    printf ("  <oneNumber name='%s'>\n", np->name);
-	    printf ("      %.20g\n", np->value);
-	    printf ("  </oneNumber>\n");
-	}
-
-	printf ("</setNumberVector>\n");
-	fflush (stdout);
-}
-
-/* tell client to update an existing switch vector property */
-void
-IDSetSwitch (const ISwitchVectorProperty *svp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<setSwitchVector\n");
-	printf ("  device='%s'\n", svp->device);
-	printf ("  name='%s'\n", svp->name);
-	printf ("  state='%s'\n", pstateStr(svp->s));
-	printf ("  timeout='%g'\n", svp->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < svp->nsp; i++) {
-	    ISwitch *sp = &svp->sp[i];
-	    printf ("  <oneSwitch name='%s'>\n", sp->name);
-	    printf ("      %s\n", sstateStr(sp->s));
-	    printf ("  </oneSwitch>\n");
-	}
-
-	printf ("</setSwitchVector>\n");
-	fflush (stdout);
-}
-
-/* tell client to update an existing lights vector property */
-void
-IDSetLight (const ILightVectorProperty *lvp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<setLightVector\n");
-	printf ("  device='%s'\n", lvp->device);
-	printf ("  name='%s'\n", lvp->name);
-	printf ("  state='%s'\n", pstateStr(lvp->s));
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < lvp->nlp; i++) {
-	    ILight *lp = &lvp->lp[i];
-	    printf ("  <oneLight name='%s'>\n", lp->name);
-	    printf ("      %s\n", pstateStr(lp->s));
-	    printf ("  </oneLight>\n");
-	}
-
-	printf ("</setLightVector>\n");
-	fflush (stdout);
-}
-
-/* tell client to update an existing BLOB vector property */
-void
-IDSetBLOB (const IBLOBVectorProperty *bvp, const char *fmt, ...)
-{
-	int i;
-
-	xmlv1();
-	printf ("<setBLOBVector\n");
-	printf ("  device='%s'\n", bvp->device);
-	printf ("  name='%s'\n", bvp->name);
-	printf ("  state='%s'\n", pstateStr(bvp->s));
-	printf ("  timeout='%g'\n", bvp->timeout);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf (">\n");
-
-	for (i = 0; i < bvp->nbp; i++) {
-	    IBLOB *bp = &bvp->bp[i];
-	    unsigned char *encblob;
-	    int j, l;
-
-	    printf ("  <oneBLOB\n");
-	    printf ("    name='%s'\n", bp->name);
-	    printf ("    size='%d'\n", bp->size);
-	    printf ("    format='%s'>\n", bp->format);
-
-	    encblob = malloc (4*bp->bloblen/3+4);
-	    l = to64frombits(encblob, bp->blob, bp->bloblen);
-	    for (j = 0; j < l; j += 72)
-		printf ("%.72s\n", encblob+j);
-	    free (encblob);
-
-	    printf ("  </oneBLOB>\n");
-	}
-
-  printf ("</setBLOBVector>\n");
-  fflush (stdout);
-}
-
-/* tell client to update min/max elements of an existing number vector property */
-void IUUpdateMinMax(const INumberVectorProperty *nvp)
-{
-  int i;
-
-  xmlv1();
-  printf ("<setNumberVector\n");
-  printf ("  device='%s'\n", nvp->device);
-  printf ("  name='%s'\n", nvp->name);
-  printf ("  state='%s'\n", pstateStr(nvp->s));
-  printf ("  timeout='%g'\n", nvp->timeout);
-  printf ("  timestamp='%s'\n", timestamp());
-  printf (">\n");
-
-  for (i = 0; i < nvp->nnp; i++) {
-    INumber *np = &nvp->np[i];
-    printf ("  <oneNumber name='%s'\n", np->name);
-    printf ("    min='%g'\n", np->min);
-    printf ("    max='%g'\n", np->max);
-    printf ("    step='%g'\n", np->step);
-    printf(">\n");
-    printf ("      %g\n", np->value);
-    printf ("  </oneNumber>\n");
-  }
-
-  printf ("</setNumberVector>\n");
-  fflush (stdout);
-}
-
-/* send client a message for a specific device or at large if !dev */
-void
-IDMessage (const char *dev, const char *fmt, ...)
-{
-
-        xmlv1();
-	printf ("<message\n");
-	if (dev)
-	    printf (" device='%s'\n", dev);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf ("/>\n");
-	fflush (stdout);
-}
-
-/* tell Client to delete the property with given name on given device, or
- * entire device if !name
- */
-void
-IDDelete (const char *dev, const char *name, const char *fmt, ...)
-{
-	xmlv1();
-	printf ("<delProperty\n  device='%s'\n", dev);
-	if (name)
-	    printf (" name='%s'\n", name);
-	printf ("  timestamp='%s'\n", timestamp());
-	if (fmt) {
-	    va_list ap;
-	    va_start (ap, fmt);
-	    printf ("  message='");
-	    vprintf (fmt, ap);
-	    printf ("'\n");
-	    va_end (ap);
-	}
-	printf ("/>\n");
-	fflush (stdout);
-}
-
-/* tell indiserver we want to snoop on the given device/property.
- * name ignored if NULL or empty.
- */
-void
-IDSnoopDevice (const char *snooped_device_name, char *snooped_property_name)
-{
-	xmlv1();
-	if (snooped_property_name && snooped_property_name[0])
-	    printf ("<getProperties device='%s' name='%s'/>\n",
-				    snooped_device_name, snooped_property_name);
-	else
-	    printf ("<getProperties device='%s'/>\n", snooped_device_name);
-	fflush (stdout);
-}
-
-/* tell indiserver whether we want BLOBs from the given snooped device.
- * silently ignored if given device is not already registered for snooping.
- */
-void 
-IDSnoopBLOBs (const char *snooped_device, BLOBHandling bh)
-{
-	const char *how;
-
-	switch (bh) {
-	case B_NEVER: how = "Never"; break;
-	case B_ALSO:  how = "Also";  break;
-	case B_ONLY:  how = "Only";  break;
-	default: return;
-	}
-
-	xmlv1();
-	printf ("<enableBLOB device='%s'>%s</enableBLOB>\n",
-						snooped_device, how);
-	fflush (stdout);
-}
-
-/* "INDI" wrappers to the more generic eventloop facility. */
-
-int
-IEAddCallback (int readfiledes, IE_CBF *fp, void *p)
-{
-	return (addCallback (readfiledes, (CBF*)fp, p));
-}
-
-void
-IERmCallback (int callbackid)
-{
-	rmCallback (callbackid);
-}
-
-int
-IEAddTimer (int millisecs, IE_TCF *fp, void *p)
-{
-	return (addTimer (millisecs, (TCF*)fp, p));
-}
-
-void
-IERmTimer (int timerid)
-{
-	rmTimer (timerid);
-}
-
-int
-IEAddWorkProc (IE_WPF *fp, void *p)
-{
-	return (addWorkProc ((WPF*)fp, p));
-}
-
-void
-IERmWorkProc (int workprocid)
-{
-	rmWorkProc (workprocid);
-}
-
-
-int
-IEDeferLoop (int maxms, int *flagp)
-{
-	return (deferLoop (maxms, flagp));
-}
-
-int
-IEDeferLoop0 (int maxms, int *flagp)
-{
-	return (deferLoop0 (maxms, flagp));
-}
-
-/* find a member of an IText vector, else NULL */
-IText *
-IUFindText  (const ITextVectorProperty *tvp, const char *name)
-{
-	int i;
-
-	for (i = 0; i < tvp->ntp; i++)
-	    if (strcmp (tvp->tp[i].name, name) == 0)
-		return (&tvp->tp[i]);
-	fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
-	return (NULL);
-}
-
-/* find a member of an INumber vector, else NULL */
-INumber *
-IUFindNumber(const INumberVectorProperty *nvp, const char *name)
-{
-	int i;
-
-	for (i = 0; i < nvp->nnp; i++)
-	    if (strcmp (nvp->np[i].name, name) == 0)
-		return (&nvp->np[i]);
-	fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
-	return (NULL);
-}
-
-/* find a member of an ISwitch vector, else NULL */
-ISwitch *
-IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
-{
-	int i;
-
-	for (i = 0; i < svp->nsp; i++)
-	    if (strcmp (svp->sp[i].name, name) == 0)
-		return (&svp->sp[i]);
-	fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
-	return (NULL);
-}
-
-/* find an ON member of an ISwitch vector, else NULL.
- * N.B. user must make sense of result with ISRule in mind.
- */
-ISwitch *
-IUFindOnSwitch(const ISwitchVectorProperty *svp)
-{
-	int i;
-
-	for (i = 0; i < svp->nsp; i++)
-	    if (svp->sp[i].s == ISS_ON)
-		return (&svp->sp[i]);
-	/*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
-	return (NULL);
-}
-
-/* Set all switches to off */
-void 
-IUResetSwitch(ISwitchVectorProperty *svp)
-{
-  int i;
-  
-  for (i = 0; i < svp->nsp; i++)
-    svp->sp[i].s = ISS_OFF;
-}
-
-/* Update property switches in accord with states and names. */
-int 
-IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
-{
- int i=0;
- ISwitch *sp;
- char sn[MAXINDINAME];
-
- /* store On switch name */
- if (svp->r == ISR_1OFMANY)
- {
- 	sp = IUFindOnSwitch(svp);
- 	if (sp) strncpy(sn, sp->name, MAXINDINAME);
- 
-	IUResetSwitch(svp);
- }
- 
- for (i = 0; i < n ; i++)
- {
-   sp = IUFindSwitch(svp, names[i]);
-	 
-   if (!sp)
-   {
-              svp->s = IPS_IDLE;
-	      IDSetSwitch(svp, "Error: %s is not a member of %s property.", names[i], svp->name);
-	      return -1;
-   }
-	 
-   sp->s = states[i]; 
- }
- 
- /* Consistency checks for ISR_1OFMANY after update. */
- if (svp->r == ISR_1OFMANY)
- {
-	int t_count=0;
-	for (i=0; i < svp->nsp; i++)
-	{
-		if (svp->sp[i].s == ISS_ON)
-			t_count++;
-	}
-	if (t_count != 1)
-	{
-		IUResetSwitch(svp);
-		sp = IUFindSwitch(svp, sn);
-		if (sp) sp->s = ISS_ON;
-		svp->s = IPS_IDLE;
-		IDSetSwitch(svp, "Error: invalid state switch for property %s. %s.", svp->name, t_count == 0 ? "No switch is on" : "Too many switches are on");
-		return -1;
-	}
- }
-		
- return 0;
-
-}
-
-/* Update property numbers in accord with values and names */
-int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
-{
-  int i=0;
-  
-  INumber *np;
-  
-  for (i = 0; i < n; i++)
-  {
-    np = IUFindNumber(nvp, names[i]);
-    if (!np)
-    {
-    	nvp->s = IPS_IDLE;
-	IDSetNumber(nvp, "Error: %s is not a member of %s property.", names[i], nvp->name);
-	return -1;
-    }
-    
-    if (values[i] < np->min || values[i] > np->max)
-    {
-       nvp->s = IPS_IDLE;
-       IDSetNumber(nvp, "Error: Invalid range. Valid range is from %g to %g", np->min, np->max);
-       return -1;
-    }
-      
-  }
-
-  /* First loop checks for error, second loop set all values atomically*/
-  for (i=0; i < n; i++)
-  {
-    np = IUFindNumber(nvp, names[i]);
-    np->value = values[i];
-  }
-
-  return 0;
-
-}
-
-/* Update property text in accord with texts and names */
-int IUUpdateText(ITextVectorProperty *tvp, char * texts[], char *names[], int n)
-{
-  int i=0;
-  
-  IText *tp;
-  
-  for (i = 0; i < n; i++)
-  {
-    tp = IUFindText(tvp, names[i]);
-    if (!tp)
-    {
-    	tvp->s = IPS_IDLE;
-	IDSetText(tvp, "Error: %s is not a member of %s property.", names[i], tvp->name);
-	return -1;
-    }
-  }
-
-  /* First loop checks for error, second loop set all values atomically*/
-  for (i=0; i < n; i++)
-  {
-    tp = IUFindText(tvp, names[i]);
-    IUSaveText(tp, texts[i]);
-  }
-
-  return 0;
-
-}
-
-/* save malloced copy of newtext in tp->text, reusing if not first time */
-void
-IUSaveText (IText *tp, const char *newtext)
-{
-	/* seed for realloc */
-	if (tp->text == NULL)
-	    tp->text = malloc (1);
-
-	/* copy in fresh string */
-	tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
-}
-
-void IUFillSwitch(ISwitch *sp, const char *name, const char * label, ISState s)
-{
-  strcpy(sp->name, name);
-  strcpy(sp->label, label);
-  sp->s = s;
-  sp->svp = NULL;
-  sp->aux = NULL;
-}
-
-void IUFillLight(ILight *lp, const char *name, const char * label, IPState s)
-{
-  strcpy(lp->name, name);
-  strcpy(lp->label, label);
-  lp->s = s;
-  lp->lvp = NULL;
-  lp->aux = NULL;
-}
-
-
-void IUFillNumber(INumber *np, const char *name, const char * label, const char *format, double min, double max, double step, double value)
-{
-
-  strcpy(np->name, name);
-  strcpy(np->label, label);
-  strcpy(np->format, format);
-  
-  np->min	= min;
-  np->max	= max;
-  np->step	= step;
-  np->value	= value;
-  np->nvp	= NULL;
-  np->aux0	= NULL;
-  np->aux1	= NULL;
-}
-
-void IUFillText(IText *tp, const char *name, const char * label, const char *initialText)
-{
-
-  strcpy(tp->name, name);
-  strcpy(tp->label, label);
-  tp->text = NULL;
-  tp->tvp  = NULL;
-  tp->aux0 = NULL;
-  tp->aux1 = NULL;
-
-  IUSaveText(tp, initialText);
-
-}
-
-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)
-{
-  strcpy(svp->device, dev);
-  strcpy(svp->name, name);
-  strcpy(svp->label, label);
-  strcpy(svp->group, group);
-  strcpy(svp->timestamp, "");
-  
-  svp->p	= p;
-  svp->r	= r;
-  svp->timeout	= timeout;
-  svp->s	= s;
-  svp->sp	= sp;
-  svp->nsp	= nsp;
-}
-
-void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char * dev, const char *name, const char *label, const char *group, IPState s)
-{
-  strcpy(lvp->device, dev);
-  strcpy(lvp->name, name);
-  strcpy(lvp->label, label);
-  strcpy(lvp->group, group);
-  strcpy(lvp->timestamp, "");
-  
-  lvp->s	= s;
-  lvp->lp	= lp;
-  lvp->nlp	= nlp;
-}
- 
-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)
-{
-  
-  strcpy(nvp->device, dev);
-  strcpy(nvp->name, name);
-  strcpy(nvp->label, label);
-  strcpy(nvp->group, group);
-  strcpy(nvp->timestamp, "");
-  
-  nvp->p	= p;
-  nvp->timeout	= timeout;
-  nvp->s	= s;
-  nvp->np	= np;
-  nvp->nnp	= nnp;
-  
-}
-
-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)
-{
-  strcpy(tvp->device, dev);
-  strcpy(tvp->name, name);
-  strcpy(tvp->label, label);
-  strcpy(tvp->group, group);
-  strcpy(tvp->timestamp, "");
-  
-  tvp->p	= p;
-  tvp->timeout	= timeout;
-  tvp->s	= s;
-  tvp->tp	= tp;
-  tvp->ntp	= ntp;
-
-}
-
-/*****************************************************************************
- * convenience functions for use in your implementation of ISSnoopDevice().
- */
-
-/* crack the snooped driver setNumberVector or defNumberVector message into
- * the given INumberVectorProperty.
- * return 0 if type, device and name match and all members are present, else
- * return -1
- */
-int
-IUSnoopNumber (XMLEle *root, INumberVectorProperty *nvp)
-{
-	char *dev, *name;
-	XMLEle *ep;
-	int i;
-
-	/* check and crack type, device, name and state */
-	if (strcmp (tagXMLEle(root)+3, "NumberVector") ||
-					crackDN (root, &dev, &name, NULL) < 0)
-	    return (-1);
-	if (strcmp (dev, nvp->device) || strcmp (name, nvp->name))
-	    return (-1);	/* not this property */
-	(void) crackIPState (findXMLAttValu (root,"state"), &nvp->s);
-
-	/* match each INumber with a oneNumber */
-	for (i = 0; i < nvp->nnp; i++) {
-	    for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (!strcmp (tagXMLEle(ep), "oneNumber") &&
-			!strcmp (nvp->np[i].name, findXMLAttValu(ep, "name"))) {
-		    if (f_scansexa (pcdataXMLEle(ep), &nvp->np[i].value) < 0)
-			return (-1);	/* bad number format */
-		    break;
-		}
-	    }
-	    if (!ep)
-		return (-1);	/* element not found */
-	}
-
-	/* ok */
-	return (0);
-}
-
-/* crack the snooped driver setTextVector or defTextVector message into
- * the given ITextVectorProperty.
- * return 0 if type, device and name match and all members are present, else
- * return -1
- */
-int
-IUSnoopText (XMLEle *root, ITextVectorProperty *tvp)
-{
-	char *dev, *name;
-	XMLEle *ep;
-	int i;
-
-	/* check and crack type, device, name and state */
-	if (strcmp (tagXMLEle(root)+3, "TextVector") ||
-					crackDN (root, &dev, &name, NULL) < 0)
-	    return (-1);
-	if (strcmp (dev, tvp->device) || strcmp (name, tvp->name))
-	    return (-1);	/* not this property */
-	(void) crackIPState (findXMLAttValu (root,"state"), &tvp->s);
-
-	/* match each IText with a oneText */
-	for (i = 0; i < tvp->ntp; i++) {
-	    for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (!strcmp (tagXMLEle(ep), "oneText") &&
-			!strcmp (tvp->tp[i].name, findXMLAttValu(ep, "name"))) {
-		    IUSaveText (&tvp->tp[i], pcdataXMLEle(ep));
-		    break;
-		}
-	    }
-	    if (!ep)
-		return (-1);	/* element not found */
-	}
-
-	/* ok */
-	return (0);
-}
-
-/* crack the snooped driver setLightVector or defLightVector message into
- * the given ILightVectorProperty. it is not necessary that all ILight names
- * be found.
- * return 0 if type, device and name match, else return -1.
- */
-int
-IUSnoopLight (XMLEle *root, ILightVectorProperty *lvp)
-{
-	char *dev, *name;
-	XMLEle *ep;
-	int i;
-
-	/* check and crack type, device, name and state */
-	if (strcmp (tagXMLEle(root)+3, "LightVector") ||
-					crackDN (root, &dev, &name, NULL) < 0)
-	    return (-1);
-	if (strcmp (dev, lvp->device) || strcmp (name, lvp->name))
-	    return (-1);	/* not this property */
-
-	(void) crackIPState (findXMLAttValu (root,"state"), &lvp->s);
-
-	/* match each oneLight with one ILight */
-	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-	    if (!strcmp (tagXMLEle(ep), "oneLight")) {
-		const char *name = findXMLAttValu (ep, "name");
-		for (i = 0; i < lvp->nlp; i++) {
-		    if (!strcmp (lvp->lp[i].name, name)) {
-			if (crackIPState(pcdataXMLEle(ep), &lvp->lp[i].s) < 0) {
-			    return (-1);	/* unrecognized state */
-			}
-			break;
-		    }
-		}
-	    }
-	}
-
-	/* ok */
-	return (0);
-}
-
-/* crack the snooped driver setSwitchVector or defSwitchVector message into the
- * given ISwitchVectorProperty. it is not necessary that all ISwitch names be
- * found.
- * return 0 if type, device and name match, else return -1.
- */
-int
-IUSnoopSwitch (XMLEle *root, ISwitchVectorProperty *svp)
-{
-	char *dev, *name;
-	XMLEle *ep;
-	int i;
-
-	/* check and crack type, device, name and state */
-	if (strcmp (tagXMLEle(root)+3, "SwitchVector") ||
-					crackDN (root, &dev, &name, NULL) < 0)
-	    return (-1);
-	if (strcmp (dev, svp->device) || strcmp (name, svp->name))
-	    return (-1);	/* not this property */
-	(void) crackIPState (findXMLAttValu (root,"state"), &svp->s);
-
-	/* match each oneSwitch with one ISwitch */
-	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-	    if (!strcmp (tagXMLEle(ep), "oneSwitch")) {
-		const char *name = findXMLAttValu (ep, "name");
-		for (i = 0; i < svp->nsp; i++) {
-		    if (!strcmp (svp->sp[i].name, name)) {
-			if (crackISState(pcdataXMLEle(ep), &svp->sp[i].s) < 0) {
-			    return (-1);	/* unrecognized state */
-			}
-			break;
-		    }
-		}
-	    }
-	}
-
-	/* ok */
-	return (0);
-}
-
-/* crack the snooped driver setBLOBVector message into the given
- * IBLOBVectorProperty. it is not necessary that all IBLOB names be found.
- * return 0 if type, device and name match, else return -1.
- * N.B. we assume any existing blob in bvp has been malloced, which we free
- *   and replace with a newly malloced blob if found.
- */
-int
-IUSnoopBLOB (XMLEle *root, IBLOBVectorProperty *bvp)
-{
-	char *dev, *name;
-	XMLEle *ep;
-	int i;
-
-	/* check and crack type, device, name and state */
-	if (strcmp (tagXMLEle(root), "setBLOBVector") ||
-					crackDN (root, &dev, &name, NULL) < 0)
-	    return (-1);
-	if (strcmp (dev, bvp->device) || strcmp (name, bvp->name))
-	    return (-1);	/* not this property */
-	(void) crackIPState (findXMLAttValu (root,"state"), &bvp->s);
-
-	/* match each oneBLOB with one IBLOB */
-	for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-	    if (!strcmp (tagXMLEle(ep), "oneBLOB")) {
-		const char *name = findXMLAttValu (ep, "name");
-		for (i = 0; i < bvp->nbp; i++) {
-		    IBLOB *bp = &bvp->bp[i];
-		    if (!strcmp (bp->name, name)) {
-			strcpy (bp->format, findXMLAttValu (ep,"format"));
-			bp->size = atof (findXMLAttValu (ep,"size"));
-			bp->bloblen = pcdatalenXMLEle(ep)+1;
-			if (bp->blob)
-			    free (bp->blob);
-			bp->blob = strcpy(malloc(bp->bloblen),pcdataXMLEle(ep));
-			break;
-		    }
-		}
-	    }
-	}
-
-	/* ok */
-	return (0);
-}
-
-/* print usage message and exit (1) */
-static void
-usage(void)
-{
-	fprintf (stderr, "Usage: %s [options]\n", me);
-	fprintf (stderr, "Purpose: INDI Device driver framework.\n");
-	fprintf (stderr, "Options:\n");
-	fprintf (stderr, " -v    : more verbose to stderr\n");
-
-	exit (1);
-}
-
-/* callback when INDI client message arrives on stdin.
- * collect and dispatch when see outter element closure.
- * exit if OS trouble or see incompatable INDI version.
- * arg is not used.
- */
-static void
-clientMsgCB (int fd, void *arg)
-{
-	char buf[1024], msg[1024], *bp;
-	int nr;
-	arg=arg;
-
-	/* one read */
-	nr = read (fd, buf, sizeof(buf));
-	if (nr < 0) {
-	    fprintf (stderr, "%s: %s\n", me, strerror(errno));
-	    exit(1);
-	}
-	if (nr == 0) {
-	    fprintf (stderr, "%s: EOF\n", me);
-	    exit(1);
-	}
-
-	/* crack and dispatch when complete */
-	for (bp = buf; nr-- > 0; bp++) {
-	    XMLEle *root = readXMLEle (clixml, *bp, msg);
-	    if (root) {
-		if (dispatch (root, msg) < 0)
-		    fprintf (stderr, "%s dispatch error: %s\n", me, msg);
-		delXMLEle (root);
-	    } else if (msg[0])
-		fprintf (stderr, "%s XML error: %s\n", me, msg);
-	}
-
-}
-
-/* crack the given INDI XML element and call driver's IS* entry points as they
- *   are recognized.
- * return 0 if ok else -1 with reason in msg[].
- * N.B. exit if getProperties does not proclaim a compatible version.
- */
-static int
-dispatch (XMLEle *root, char msg[])
-{
-	char *rtag = tagXMLEle(root);
-	XMLEle *ep;
-	int n,i=0;
-
-	if (verbose)
-	    prXMLEle (stderr, root, 0);
-
-	/* check tag in surmised decreasing order of likelyhood */
-
-	if (!strcmp (rtag, "newNumberVector")) {
-	    static double *doubles;
-	    static char **names;
-	    static int maxn;
-	    char *dev, *name;
-
-	    /* pull out device and name */
-	    if (crackDN (root, &dev, &name, msg) < 0)
-		return (-1);
-
-	    /* seed for reallocs */
-	    if (!doubles) {
-		doubles = (double *) malloc (1);
-		names = (char **) malloc (1);
-	    }
-
-	    /* pull out each name/value pair */
-	    for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (strcmp (tagXMLEle(ep), "oneNumber") == 0) {
-		    XMLAtt *na = findXMLAtt (ep, "name");
-		    if (na) {
-			if (n >= maxn) {
-			    /* grow for this and another */
-			    int newsz = (maxn=n+1)*sizeof(double);
-			    doubles = (double *) realloc(doubles,newsz);
-			    newsz = maxn*sizeof(char *);
-			    names = (char **) realloc (names, newsz);
-			}
-			if (f_scansexa (pcdataXMLEle(ep), &doubles[n]) < 0)
-			    IDMessage (dev,"%s: Bad format %s", name,
-							    pcdataXMLEle(ep));
-			else
-			    names[n++] = valuXMLAtt(na);
-		    }
-		}
-	    }
-	    
-	    /* insure property is not RO */
-	    for (i=0; i < nroCheck; i++)
-	    {
-	      if (!strcmp(roCheck[i].propName, name))
-	      {
-	       if (roCheck[i].perm == IP_RO)
-	         return -1;
-	      }
-	    }
-
-	    /* invoke driver if something to do, but not an error if not */
-	    if (n > 0)
-		ISNewNumber (dev, name, doubles, names, n);
-	    else
-		IDMessage(dev,"%s: newNumberVector with no valid members",name);
-	    return (0);
-	}
-
-	if (!strcmp (rtag, "newSwitchVector")) {
-	    static ISState *states;
-	    static char **names;
-	    static int maxn;
-	    char *dev, *name;
-	    XMLEle *ep;
-
-	    /* pull out device and name */
-	    if (crackDN (root, &dev, &name, msg) < 0)
-		return (-1);
-
-	    /* seed for reallocs */
-	    if (!states) {
-		states = (ISState *) malloc (1);
-		names = (char **) malloc (1);
-	    }
-
-	    /* pull out each name/state pair */
-	    for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (strcmp (tagXMLEle(ep), "oneSwitch") == 0) {
-		    XMLAtt *na = findXMLAtt (ep, "name");
-		    if (na) {
-			if (n >= maxn) {
-			    int newsz = (maxn=n+1)*sizeof(ISState);
-			    states = (ISState *) realloc(states, newsz);
-			    newsz = maxn*sizeof(char *);
-			    names = (char **) realloc (names, newsz);
-			}
-			if (strcmp (pcdataXMLEle(ep),"On") == 0) {
-			    states[n] = ISS_ON;
-			    names[n] = valuXMLAtt(na);
-			    n++;
-			} else if (strcmp (pcdataXMLEle(ep),"Off") == 0) {
-			    states[n] = ISS_OFF;
-			    names[n] = valuXMLAtt(na);
-			    n++;
-			} else 
-			    IDMessage (dev, "%s: must be On or Off: %s", name,
-							    pcdataXMLEle(ep));
-		    }
-		}
-	    }
-
-	    /* insure property is not RO */
-	    for (i=0; i < nroCheck; i++)
-	    {
-	      if (!strcmp(roCheck[i].propName, name))
-	      {
-	       if (roCheck[i].perm == IP_RO)
-	         return -1;
-	      }
-	    }
-	    
-	    /* invoke driver if something to do, but not an error if not */
-	    if (n > 0)
-		ISNewSwitch (dev, name, states, names, n);
-	    else
-		IDMessage(dev,"%s: newSwitchVector with no valid members",name);
-	    return (0);
-	}
-
-	if (!strcmp (rtag, "newTextVector")) {
-	    static char **texts;
-	    static char **names;
-	    static int maxn;
-	    char *dev, *name;
-
-	    /* pull out device and name */
-	    if (crackDN (root, &dev, &name, msg) < 0)
-		return (-1);
-
-	    /* seed for reallocs */
-	    if (!texts) {
-		texts = (char **) malloc (1);
-		names = (char **) malloc (1);
-	    }
-
-	    /* pull out each name/text pair */
-	    for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (strcmp (tagXMLEle(ep), "oneText") == 0) {
-		    XMLAtt *na = findXMLAtt (ep, "name");
-		    if (na) {
-			if (n >= maxn) {
-			    int newsz = (maxn=n+1)*sizeof(char *);
-			    texts = (char **) realloc (texts, newsz);
-			    names = (char **) realloc (names, newsz);
-			}
-			texts[n] = pcdataXMLEle(ep);
-			names[n] = valuXMLAtt(na);
-			n++;
-		    }
-		}
-	    }
-	    
-	    /* insure property is not RO */
-	    for (i=0; i < nroCheck; i++)
-	    {
-	      if (!strcmp(roCheck[i].propName, name))
-	      {
-	       if (roCheck[i].perm == IP_RO)
-	         return -1;
-	      }
-	    }
-
-	    /* invoke driver if something to do, but not an error if not */
-	    if (n > 0)
-		ISNewText (dev, name, texts, names, n);
-	    else
-		IDMessage (dev, "%s: set with no valid members", name);
-	    return (0);
-	}
-
-	if (!strcmp (rtag, "newBLOBVector")) {
-	    static char **blobs;
-	    static char **names;
-	    static char **formats;
-	    static int *blobsizes;
-	    static int *sizes;
-	    static int maxn;
-	    char *dev, *name;
-	    int i;
-
-	    /* pull out device and name */
-	    if (crackDN (root, &dev, &name, msg) < 0)
-		return (-1);
-
-	    /* seed for reallocs */
-	    if (!blobs) {
-		blobs = (char **) malloc (1);
-		names = (char **) malloc (1);
-		formats = (char **) malloc (1);
-		blobsizes = (int *) malloc (1);
-		sizes = (int *) malloc (1);
-	    }
-
-	    /* pull out each name/BLOB pair, decode */
-	    for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0)) {
-		if (strcmp (tagXMLEle(ep), "oneBLOB") == 0) {
-		    XMLAtt *na = findXMLAtt (ep, "name");
-		    XMLAtt *fa = findXMLAtt (ep, "format");
-		    XMLAtt *sa = findXMLAtt (ep, "size");
-		    if (na && fa && sa) {
-			if (n >= maxn) {
-			    int newsz = (maxn=n+1)*sizeof(char *);
-			    blobs = (char **) realloc (blobs, newsz);
-			    names = (char **) realloc (names, newsz);
-			    formats = (char **) realloc(formats,newsz);
-			    newsz = maxn*sizeof(int);
-			    sizes = (int *) realloc(sizes,newsz);
-			    blobsizes = (int *) realloc(blobsizes,newsz);
-			}
-			blobs[n] = malloc (3*pcdatalenXMLEle(ep)/4);
-			blobsizes[n] = from64tobits(blobs[n], pcdataXMLEle(ep));
-			names[n] = valuXMLAtt(na);
-			formats[n] = valuXMLAtt(fa);
-			sizes[n] = atoi(valuXMLAtt(sa));
-			n++;
-		    }
-		}
-	    }
-
-	    /* invoke driver if something to do, but not an error if not */
-	    if (n > 0) {
-		ISNewBLOB (dev, name, sizes, blobsizes, blobs, formats,names,n);
-		for (i = 0; i < n; i++)
-		    free (blobs[i]);
-	    } else
-		IDMessage (dev, "%s: newBLOBVector with no valid members",name);
-	    return (0);
-	}
-
-	if (!strcmp (rtag, "getProperties")) {
-	    XMLAtt *ap;
-	    double v;
-
-	    /* check version */
-	    ap = findXMLAtt (root, "version");
-	    if (!ap) {
-		fprintf (stderr, "%s: getProperties missing version\n", me);
-		exit(1);
-	    }
-	    v = atof (valuXMLAtt(ap));
-	    if (v > INDIV) {
-		fprintf (stderr, "%s: client version %g > %g\n", me, v, INDIV);
-		exit(1);
-	    }
-
-	    /* ok */
-	    ap = findXMLAtt (root, "device");
-	    ISGetProperties (ap ? valuXMLAtt(ap) : NULL);
-	    return (0);
-	}
-
-	/* other commands might be from a snooped device.
-	 * we don't know here which devices are being snooped so we send
-	 * all remaining valid messages
-	 */
-	if (        !strcmp (rtag, "setNumberVector") ||
-		    !strcmp (rtag, "setTextVector") ||
-		    !strcmp (rtag, "setLightVector") ||
-		    !strcmp (rtag, "setSwitchVector") ||
-		    !strcmp (rtag, "setBLOBVector") ||
-		    !strcmp (rtag, "defNumberVector") ||
-		    !strcmp (rtag, "defTextVector") ||
-		    !strcmp (rtag, "defLightVector") ||
-		    !strcmp (rtag, "defSwitchVector") ||
-		    !strcmp (rtag, "defBLOBVector") ||
-		    !strcmp (rtag, "message") ||
-		    !strcmp (rtag, "delProperty")) {
-	    ISSnoopDevice (root);
-	    return (0);
-	}
-
-	sprintf (msg, "Unknown command: %s", rtag);
-	return(1);
-}
-
-/* pull out device and name attributes from root.
- * return 0 if ok else -1 with reason in msg[].
- */
-static int
-crackDN (XMLEle *root, char **dev, char **name, char msg[])
-{
-	XMLAtt *ap;
-
-	ap = findXMLAtt (root, "device");
-	if (!ap) {
-	    sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
-	    return (-1);
-	}
-	*dev = valuXMLAtt(ap);
-
-	ap = findXMLAtt (root, "name");
-	if (!ap) {
-	    sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
-	    return (-1);
-	}
-	*name = valuXMLAtt(ap);
-
-	return (0);
-}
-
-/* return static string corresponding to the given property or light state */
-const char *
-pstateStr (IPState s)
-{
-	switch (s) {
-	case IPS_IDLE:  return ("Idle");
-	case IPS_OK:    return ("Ok");
-	case IPS_BUSY:  return ("Busy");
-	case IPS_ALERT: return ("Alert");
-	default:
-	    fprintf (stderr, "Impossible IPState %d\n", s);
-	    exit(1);
-	}
-}
-
-/* crack string into IPState.
- * return 0 if ok, else -1
- */
-static int
-crackIPState (const char *str, IPState *ip)
-{
-	     if (!strcmp (str, "Idle"))  *ip = IPS_IDLE;
-	else if (!strcmp (str, "Ok"))    *ip = IPS_OK;
-	else if (!strcmp (str, "Busy"))  *ip = IPS_BUSY;
-	else if (!strcmp (str, "Alert")) *ip = IPS_ALERT;
-	else return (-1);
-	return (0);
-}
-
-/* crack string into ISState.
- * return 0 if ok, else -1
- */
-static int
-crackISState (const char *str, ISState *ip)
-{
-	     if (!strcmp (str, "On"))  *ip = ISS_ON;
-	else if (!strcmp (str, "Off")) *ip = ISS_OFF;
-	else return (-1);
-	return (0);
-}
-
-/* return static string corresponding to the given switch state */
-const char *
-sstateStr (ISState s)
-{
-	switch (s) {
-	case ISS_ON:  return ("On");
-	case ISS_OFF: return ("Off");
-	default:
-	    fprintf (stderr, "Impossible ISState %d\n", s);
-	    exit(1);
-	}
-}
-
-/* return static string corresponding to the given Rule */
-const char *
-ruleStr (ISRule r)
-{
-	switch (r) {
-	case ISR_1OFMANY: return ("OneOfMany");
-	case ISR_ATMOST1: return ("AtMostOne");
-	case ISR_NOFMANY: return ("AnyOfMany");
-	default:
-	    fprintf (stderr, "Impossible ISRule %d\n", r);
-	    exit(1);
-	}
-}
-
-/* return static string corresponding to the given IPerm */
-const char *
-permStr (IPerm p)
-{
-	switch (p) {
-	case IP_RO: return ("ro");
-	case IP_WO: return ("wo");
-	case IP_RW: return ("rw");
-	default:
-	    fprintf (stderr, "Impossible IPerm %d\n", p);
-	    exit(1);
-	}
-}
-
-/* print the boilerplate comment introducing xml */
-static void
-xmlv1()
-{
-	printf ("<?xml version='1.0'?>\n");
-}
Index: /BAORadio/libindi/libindi/indiserver.c
===================================================================
--- /BAORadio/libindi/libindi/indiserver.c	(revision 500)
+++ /BAORadio/libindi/libindi/indiserver.c	(revision 501)
@@ -92,4 +92,11 @@
 } Snoopee;
 
+struct
+{
+    const char *name;                      /* Path to FIFO for dynamic startups & shutdowns of drivers */
+    int fd;
+    FILE *fs;
+} fifo;
+
 /* info for each connected client */
 typedef struct {
@@ -109,6 +116,7 @@
 /* info for each connected driver */
 typedef struct {
-    const char *name;				/* persistent malloced name */
+    char name[MAXINDIDEVICE];		/* persistent name */
     char dev[MAXINDIDEVICE];		/* device served by this driver */
+    int active;				/* 1 when this record is in use */
     Snoopee *sprops;			/* malloced array of props we snoop */
     int nsprops;			/* n entries in sprops[] */
@@ -136,6 +144,8 @@
 static void noZombies (void);
 static void noSIGPIPE (void);
+static void indiFIFO(void);
 static void indiRun (void);
 static void indiListen (void);
+static void newFIFO(void);
 static void newClient (void);
 static int newClSocket (void);
@@ -146,5 +156,5 @@
 static void startRemoteDvr (DvrInfo *dp);
 static int openINDIServer (char host[], int indi_port);
-static void restartDvr (DvrInfo *dp);
+static void shutdownDvr (DvrInfo *dp, int restart);
 static void q2RDrivers (const char *dev, Msg *mp, XMLEle *root);
 static void q2SDrivers (int isblob, const char *dev, const char *name, Msg *mp,
@@ -209,4 +219,12 @@
 		    ac--;
 		    break;
+                case 'f':
+                    if (ac < 2) {
+                        fprintf (stderr, "-f requires fifo node\n");
+                        usage();
+                    }
+                    fifo.name = *++av;
+                    ac--;
+                    break;
 		case 'v':
 		    verbose++;
@@ -218,6 +236,6 @@
 
 	/* at this point there are ac args in av[] to name our drivers */
-	if (ac == 0)
-	    usage();
+        if (ac == 0 && !fifo.name)
+            usage();
 
 	/* take care of some unixisms */
@@ -230,15 +248,18 @@
 
 	/* create driver info array all at once since size never changes */
-	ndvrinfo = ac;
+        ndvrinfo = ac;
 	dvrinfo = (DvrInfo *) calloc (ndvrinfo, sizeof(DvrInfo));
 
 	/* start each driver */
-	while (ac-- > 0) {
-	    dvrinfo[ac].name = *av++;
+        while (ac-- > 0) {
+            strcpy(dvrinfo[ac].name, *av++);
 	    startDvr (&dvrinfo[ac]);
-	}
+        }
 
 	/* announce we are online */
 	indiListen();
+
+        /* Load up FIFO, if available */
+        indiFIFO();
 
 	/* handle new clients and all io */
@@ -271,11 +292,12 @@
 	fprintf (stderr, "Code %s. Protocol %g.\n", "$Revision: 726523 $", INDIV);
 	fprintf (stderr, "Options:\n");
-	fprintf (stderr, " -l d  : log driver messages to <d>/YYYY-MM-DD.islog\n");
-	fprintf (stderr, " -m m  : kill client if gets more than this many MB behind, default %d\n", DEFMAXQSIZ);
-	fprintf (stderr, " -p p  : alternate IP port, default %d\n", INDIPORT);
-	fprintf (stderr, " -v    : show key events, no traffic\n");
-	fprintf (stderr, " -vv   : -v + key message content\n");
-	fprintf (stderr, " -vvv  : -vv + complete xml\n");
-	fprintf (stderr, "driver : executable or device@host[:port]\n");
+        fprintf (stderr, " -l d     : log driver messages to <d>/YYYY-MM-DD.islog\n");
+        fprintf (stderr, " -m m     : kill client if gets more than this many MB behind, default %d\n", DEFMAXQSIZ);
+        fprintf (stderr, " -p p     : alternate IP port, default %d\n", INDIPORT);
+        fprintf (stderr, " -f path  : Path to fifo for dynamic startup and shutdown of drivers.\n");
+        fprintf (stderr, " -v       : show key events, no traffic\n");
+        fprintf (stderr, " -vv      : -v + key message content\n");
+        fprintf (stderr, " -vvv     : -vv + complete xml\n");
+        fprintf (stderr, "driver    : executable or device@host[:port]\n");
 
 	exit (2);
@@ -307,4 +329,32 @@
 }
 
+static DvrInfo * allocDvr ()
+{
+    DvrInfo *dp = NULL;
+    int dvi;
+
+/* try to reuse a drivber slot, else add one */
+for (dvi = 0; dvi < ndvrinfo; dvi++)
+    if (!(dp = &dvrinfo[dvi])->active)
+        break;
+if (dvi == ndvrinfo)
+{
+    /* grow dvrinfo */
+    dvrinfo = (DvrInfo *) realloc (dvrinfo, (ndvrinfo+1)*sizeof(DvrInfo));
+    if (!dvrinfo) {
+        fprintf (stderr, "no memory for new drivers\n");
+        Bye();
+    }
+    dp = &dvrinfo[ndvrinfo++];
+}
+
+/* rig up new dvrinfo entry */
+memset (dp, 0, sizeof(*dp));
+dp->active = 1;
+
+return dp;
+
+}
+
 /* start the given INDI driver process or connection.
  * exit if trouble.
@@ -382,8 +432,9 @@
 	dp->efd = ep[0];
 	dp->lp = newLilXML();
-	dp->msgq = newFQ(1);
+        dp->msgq = newFQ(1);
 	dp->sprops = (Snoopee*) malloc (1);	/* seed for realloc */
 	dp->nsprops = 0;
 	dp->nsent = 0;
+        dp->active = 1;
 
 	/* first message primes driver to report its properties -- dev known
@@ -436,4 +487,5 @@
 	dp->nsprops = 0;
 	dp->nsent = 0;
+        dp->active = 1;
 
 	/* N.B. storing name now is key to limiting outbound traffic to this
@@ -544,4 +596,21 @@
 }
 
+/* Attempt to open up FIFO */
+static void indiFIFO(void)
+{
+    /* Open up FIFO, if available */
+    if (fifo.name)
+    {
+        fifo.fd = open(fifo.name, O_RDONLY);
+                  if (fifo.fd < 0)
+                  {
+                       fprintf(stderr, "%s: open(%s): %s.\n", indi_tstamp(NULL), fifo.name, strerror(errno));
+                        Bye();
+                   }
+
+        fifo.fs = fdopen(fifo.fd, "r");
+    }
+}
+
 /* service traffic from clients and drivers */
 static void
@@ -549,5 +618,5 @@
 {
 	fd_set rs, ws;
-	int maxfd;
+        int maxfd=0;
 	int i, s;
 
@@ -556,7 +625,14 @@
 	FD_ZERO(&rs);
 
+        if (fifo.name && fifo.fd > 0)
+        {
+           FD_SET(fifo.fd, &rs);
+           maxfd = fifo.fd;
+        }
+
 	/* always listen for new clients */
 	FD_SET(lsocket, &rs);
-	maxfd = lsocket;
+        if (lsocket > maxfd)
+                maxfd = lsocket;
 
 	/* add all client readers and client writers with work to send */
@@ -573,19 +649,25 @@
 
 	/* add all driver readers and driver writers with work to send */
-	for (i = 0; i < ndvrinfo; i++) {
+        for (i = 0; i < ndvrinfo; i++)
+        {
 	    DvrInfo *dp = &dvrinfo[i];
-	    FD_SET(dp->rfd, &rs);
-	    if (dp->rfd > maxfd)
-		maxfd = dp->rfd;
-	    if (dp->pid != REMOTEDVR) {
-		FD_SET(dp->efd, &rs);
-		if (dp->efd > maxfd)
-		    maxfd = dp->efd;
-	    }
-	    if (nFQ(dp->msgq) > 0) {
-		FD_SET(dp->wfd, &ws);
-		if (dp->wfd > maxfd)
-		    maxfd = dp->wfd;
-	    }
+            if (dp->active)
+            {
+                FD_SET(dp->rfd, &rs);
+                if (dp->rfd > maxfd)
+                   maxfd = dp->rfd;
+                if (dp->pid != REMOTEDVR)
+                {
+                   FD_SET(dp->efd, &rs);
+                   if (dp->efd > maxfd)
+                      maxfd = dp->efd;
+                }
+                if (nFQ(dp->msgq) > 0)
+                {
+                   FD_SET(dp->wfd, &ws);
+                   if (dp->wfd > maxfd)
+                       maxfd = dp->wfd;
+                }
+            }
 	}
 
@@ -597,4 +679,11 @@
 	    Bye();
 	}
+
+
+        /* new command from FIFO? */
+        if (s > 0 && FD_ISSET(fifo.fd, &rs)) {
+            newFIFO();
+            s--;
+        }
 
 	/* new client? */
@@ -642,4 +731,156 @@
 }
 
+/* Read commands from FIFO and process them. Start/stop drivers accordingly */
+static void newFIFO(void)
+{
+    char line[MAXRBUF], tDriver[MAXRBUF], tConfig[MAXRBUF], tDev[MAXRBUF];
+    static char *envDev=NULL, *envConfig=NULL;
+    const char *delm = " ";
+    char *token, *cp;
+    DvrInfo *dp = NULL;
+    int startCmd=0;
+
+    if (envDev == NULL)
+        envDev = (char *) malloc(MAXRBUF* sizeof(char));
+    if (envConfig == NULL)
+        envConfig = (char *) malloc(MAXRBUF * sizeof(char));
+
+    while ( fgets (line, MAXRBUF, fifo.fs) != NULL)
+    {
+        //fprintf(stderr, "FIFO: %s\n", line);
+        tDev[0] = '\0', tDriver[0] = '\0', tConfig[0] = '\0', envDev[0] = '\0', envConfig[0] = '\0';
+        cp = strdup(line);
+
+        token = strsep(&cp, delm);
+
+        if (!strcmp(token, "start") || !strcmp(token, "stop"))
+        {
+                if (!strcmp(token, "start"))
+                    startCmd = 1;
+
+                token = strsep(&cp, delm);
+
+                if (!token)
+                    continue;
+
+               strncpy(tDriver, token, MAXRBUF);
+
+               if (verbose)
+                fprintf(stderr, "FIFO: Request for %s driver: %s\n", (startCmd == 1) ? "starting" : "stopping", tDriver);
+
+               /* Find more name + config */
+               token = strsep(&cp, delm);
+
+               if (token)
+               {
+                 /* If config file detected, copy it */
+                if (strstr(token, ".xml"))                 
+                    strncpy(tConfig, token, MAXRBUF);
+                /* Get rid of quotes */
+                else if (strstr(token, "\"") || strstr(token, "'"))
+                {
+                    strncat(tDev, ++token, MAXRBUF);
+                    while (token = strsep(&cp, delm) )
+                   {
+                     strcat(tDev, " ");
+                     strncat(tDev, token, MAXRBUF);
+                     if (strstr(token, "\"") || strstr(token, "'"))
+                     {
+                         tDev[strlen(tDev)-1] = '\0';
+                         break;
+                     }
+                    }
+                 }
+                 else
+                     strncpy(tDev, token, MAXRBUF);
+
+                  /* Find config, if there is any */
+                  token = strsep(&cp, delm);
+                  if (token)
+                  {
+                      /* Get rid of quotes */
+                      if (strstr(token, "\"") || strstr(token, "'"))
+                      {
+                       strncat(tConfig, ++token, MAXRBUF);
+                       while (token = strsep(&cp, delm) )
+                       {
+                          strcat(tConfig, " ");
+                          strncat(tConfig, token, MAXRBUF);
+
+                          if (strstr(token, "\"") || strstr(token, "'"))
+                          {
+                                 tConfig[strlen(tConfig)-1] = '\0';
+                                 break;
+                          }
+                       }
+                      }
+                       else
+                           strncpy(tConfig, token, MAXRBUF);
+                  }
+              }
+
+               /* Did we find device name? */
+               if (tDev[0])
+               {
+                 snprintf(envDev, MAXRBUF, "INDIDEV=%s", tDev);
+                 //fprintf(stderr, "With name: %s\n", envDev);
+                 putenv(envDev);
+
+                 //fprintf(stderr, "envionment check INDIDEV: %s\n", getenv("INDIDEV"));
+               }
+
+               /* Did we find config file */
+               if (tConfig[0])
+               {
+                   snprintf(envConfig, MAXRBUF, "INDICONFIG=%s", tConfig);
+                   //fprintf(stderr, "With config: %s\n", envConfig);
+                   putenv(envConfig);
+               }
+
+               if (startCmd)
+               {
+                   if (verbose)
+                        fprintf(stderr, "FIFO: Starting driver %s\n", tDriver);
+                    dp = allocDvr();
+                    strncpy(dp->name, tDriver, MAXINDIDEVICE);
+                    strncpy(dp->dev, tDev, MAXINDIDEVICE);
+                    startDvr (dp);
+              }
+               else
+               {
+                  for (dp = dvrinfo; dp < &dvrinfo[ndvrinfo]; dp++)
+                   {
+                       if (!strcmp(dp->name, tDriver))
+                       {
+                           /* If device name is given, check against it before shutting down */
+                           if (tDev[0] && strcmp(dp->dev, tDev))
+                               continue;
+
+                           if (verbose)
+                               fprintf(stderr, "FIFO: Shutting down driver: %s\n", tDriver);
+
+                           shutdownDvr(dp, 0);
+
+                               /* Inform clients that this driver is dead */
+                               XMLEle *root = addXMLEle (NULL, "delProperty");
+                               addXMLAtt(root, "device", dp->dev);
+                               Msg * mp = newMsg();
+
+                               q2Clients(NULL, 0, dp->dev, NULL, mp, root);
+                               if (mp->count > 0)
+                                   setMsgXMLEle (mp, root);
+                               else
+                                   freeMsg (mp);
+                               delXMLEle (root);
+
+                           break;
+
+                       }
+                   }
+               }
+         }
+    }
+}
+
 /* prepare for new client arriving on lsocket.
  * exit if trouble.
@@ -753,5 +994,5 @@
 		/* echo new* commands back to other clients */
 		if (!strncmp (roottag, "new", 3)) {
-		    if (q2Clients (cp, isblob, dev, name, mp, root) < 0)
+                    if (q2Clients (cp, isblob, dev, name, mp, root) < 0)
 			shutany++;
 		}
@@ -798,5 +1039,5 @@
 		fprintf (stderr, "%s: Driver %s: stdin EOF\n",
 							indi_tstamp(NULL), dp->name);
-	    restartDvr (dp);
+            shutdownDvr (dp, 1);
 	    return (-1);
 	}
@@ -872,5 +1113,5 @@
 		fprintf (stderr, "%s: Driver %s: XML read: %.*s\n", ts,
 							    dp->name, nr, buf);
-		restartDvr (dp);
+                shutdownDvr (dp, 1);
 		return (-1);
 	    }
@@ -899,5 +1140,5 @@
 		fprintf (stderr, "%s: Driver %s: stderr EOF\n",
 							indi_tstamp(NULL), dp->name);
-	    restartDvr (dp);
+            shutdownDvr (dp, 1);
 	    return (-1);
 	}
@@ -949,5 +1190,5 @@
 /* close down the given driver and restart */
 static void
-restartDvr (DvrInfo *dp)
+shutdownDvr (DvrInfo *dp, int restart)
 {
 	Msg *mp;
@@ -960,5 +1201,5 @@
 	} else {
 	    /* local pipe connection */
-	    kill (dp->pid, SIGKILL);	/* we've insured there are no zombies */
+            kill (dp->pid, SIGKILL);	/* we've insured there are no zombies */
 	    close (dp->wfd);
 	    close (dp->rfd);
@@ -969,4 +1210,7 @@
 	free (dp->sprops);
 	delLilXML (dp->lp);
+
+        /* ok now to recycle */
+        dp->active = 0;
 
 	/* decrement and possibly free any unsent messages for this client */
@@ -976,7 +1220,11 @@
 	delFQ (dp->msgq);
 
-	fprintf (stderr, "%s: Driver %s: restart #%d\n", indi_tstamp(NULL),
-						    dp->name, ++dp->restarts);
-	startDvr (dp);
+        if (restart)
+        {
+            fprintf (stderr, "%s: Driver %s: restart #%d\n", indi_tstamp(NULL),
+                                                    dp->name, ++dp->restarts);
+            startDvr (dp);
+        }
+
 }
 
@@ -1285,5 +1533,5 @@
 		fprintf (stderr, "%s: Driver %s: write: %s\n", indi_tstamp(NULL),
 						    dp->name, strerror(errno));
-	    restartDvr (dp);
+            shutdownDvr (dp, 1);
 	    return (-1);
 	}
@@ -1325,5 +1573,5 @@
 	    Property *pp = &cp->props[i];
 	    if (!strcmp (pp->dev, dev) &&
-				    (!pp->name[0] || !strcmp(pp->name, name)))
+                                    (!pp->name[0] || !strcmp(pp->name, name)))
 		return (0);
 	}
@@ -1459,29 +1707,29 @@
 logDMsg (XMLEle *root, const char *dev)
 {
-	char stamp[64];
-	char logfn[1024];
-	const char *ts, *ms;
-	FILE *fp;
-
-	/* get message, if any */
-	ms = findXMLAttValu (root, "message");
-	if (!ms[0])
-	    return;
-
-	/* get timestamp now if not provided */
-	ts = findXMLAttValu (root, "timestamp");
-	if (!ts[0])
-	{
-	    indi_tstamp (stamp);
-	    ts = stamp;
-	}
-
-	/* append to log file, name is date portion of time stamp */
-	sprintf (logfn, "%s/%.10s.islog", ldir, ts);
-	fp = fopen (logfn, "a");
-	if (!fp)
-	    return;	/* oh well */
-	fprintf (fp, "%s: %s: %s\n", ts, dev, ms);
-	fclose (fp);
+        char stamp[64];
+        char logfn[1024];
+        const char *ts, *ms;
+        FILE *fp;
+
+        /* get message, if any */
+        ms = findXMLAttValu (root, "message");
+        if (!ms[0])
+            return;
+
+        /* get timestamp now if not provided */
+        ts = findXMLAttValu (root, "timestamp");
+        if (!ts[0])
+        {
+            indi_tstamp (stamp);
+            ts = stamp;
+        }
+
+        /* append to log file, name is date portion of time stamp */
+        sprintf (logfn, "%s/%.10s.islog", ldir, ts);
+        fp = fopen (logfn, "a");
+        if (!fp)
+            return;	/* oh well */
+        fprintf (fp, "%s: %s: %s\n", ts, dev, ms);
+        fclose (fp);
 }
 
Index: /BAORadio/libindi/libindi/libindi.pc.cmake
===================================================================
--- /BAORadio/libindi/libindi/libindi.pc.cmake	(revision 500)
+++ /BAORadio/libindi/libindi/libindi.pc.cmake	(revision 501)
@@ -10,2 +10,3 @@
 Libs: -L@LIB_DESTINATION@ -lindi
 Cflags: -I@INCLUDE_INSTALL_DIR@ -@INCLUDE_INSTALL_DIR@/libindi
+
Index: /BAORadio/libindi/libindi/libs/indicom.c
===================================================================
--- /BAORadio/libindi/libindi/libs/indicom.c	(revision 500)
+++ /BAORadio/libindi/libindi/libs/indicom.c	(revision 501)
@@ -24,12 +24,4 @@
 */
 
-/* needed for sincos() in math.h */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#ifdef _WIN32
-#define CX _CX
-#define CY _CY
-#endif
 #include <stdlib.h>
 #include <math.h>
@@ -40,11 +32,11 @@
 #include <errno.h>
 #include <stdarg.h>
-
-#include <config.h>
+#include <sys/param.h>
+
+//#include <config.h>
 
 #ifdef HAVE_NOVA_H
 #include <libnova.h>
 #endif
-
 
 #include "indicom.h"
@@ -52,11 +44,4 @@
 #undef CX
 #undef CY
-#endif
-const char * Direction[] = { "North", "West", "East", "South", "All"};
-const char * SolarSystem[] = { "Mercury", "Venus", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"};
-
-/* make it compile on solaris */
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338327950288419716939937510582097494459
 #endif
 
@@ -67,4 +52,8 @@
 #define PARITY_ODD     2
 #endif
+
+#define MAXRBUF         2048
+
+#include "indidevapi.h"
 
 void getSexComponents(double value, int *d, int *m, int *s);
@@ -387,4 +376,284 @@
 }
 
+#ifdef BSD
+// BSD - OSX version
+int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
+{
+       int	t_fd = -1;
+       int bps;
+       char msg[80];
+    int	handshake;
+    struct termios	tty_setting;
+
+    // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
+    // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
+    // See open(2) ("man 2 open") for details.
+
+    t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (t_fd == -1)
+    {
+        printf("Error opening serial port %s - %s(%d).\n",
+               device, strerror(errno), errno);
+        goto error;
+    }
+
+    // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
+    // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
+    // processes.
+    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
+
+    if (ioctl(t_fd, TIOCEXCL) == -1)
+    {
+        printf("Error setting TIOCEXCL on %s - %s(%d).\n",
+            device, strerror(errno), errno);
+        goto error;
+    }
+
+    // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
+    // See fcntl(2) ("man 2 fcntl") for details.
+
+    if (fcntl(t_fd, F_SETFL, 0) == -1)
+    {
+        printf("Error clearing O_NONBLOCK %s - %s(%d).\n",
+            device, strerror(errno), errno);
+        goto error;
+    }
+
+    // Get the current options and save them so we can restore the default settings later.
+    if (tcgetattr(t_fd, &tty_setting) == -1)
+    {
+        printf("Error getting tty attributes %s - %s(%d).\n",
+            device, strerror(errno), errno);
+        goto error;
+    }
+
+    // Set raw input (non-canonical) mode, with reads blocking until either a single character
+    // has been received or a one second timeout expires.
+    // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
+
+    cfmakeraw(&tty_setting);
+    tty_setting.c_cc[VMIN] = 1;
+    tty_setting.c_cc[VTIME] = 10;
+
+    // The baud rate, word length, and handshake options can be set as follows:
+        switch (bit_rate) {
+                case 0:
+                        bps = B0;
+                        break;
+                case 50:
+                        bps = B50;
+                        break;
+                case 75:
+                        bps = B75;
+                        break;
+                case 110:
+                        bps = B110;
+                        break;
+                case 134:
+                        bps = B134;
+                        break;
+                case 150:
+                        bps = B150;
+                        break;
+                case 200:
+                        bps = B200;
+                        break;
+                case 300:
+                        bps = B300;
+                        break;
+                case 600:
+                        bps = B600;
+                        break;
+                case 1200:
+                        bps = B1200;
+                        break;
+                case 1800:
+                        bps = B1800;
+                        break;
+                case 2400:
+                        bps = B2400;
+                        break;
+                case 4800:
+                        bps = B4800;
+                        break;
+                case 9600:
+                        bps = B9600;
+                        break;
+                case 19200:
+                        bps = B19200;
+                        break;
+                case 38400:
+                        bps = B38400;
+                        break;
+                case 57600:
+                        bps = B57600;
+                        break;
+                case 115200:
+                        bps = B115200;
+                        break;
+                case 230400:
+                        bps = B230400;
+                        break;
+                default:
+                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate)  0)
+                                perror(NULL);
+                        else
+                                perror(msg);
+                        return TTY_PARAM_ERROR;
+        }
+
+     cfsetspeed(&tty_setting, bps);		// Set baud rate
+        /* word size */
+        switch (word_size) {
+                case 5:
+                        tty_setting.c_cflag |= CS5;
+                        break;
+                case 6:
+                        tty_setting.c_cflag |= CS6;
+                        break;
+                case 7:
+                        tty_setting.c_cflag |= CS7;
+                        break;
+                case 8:
+                        tty_setting.c_cflag |= CS8;
+                        break;
+                default:
+
+                        fprintf( stderr, "Default\n") ;
+                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size)  0)
+                                perror(NULL);
+                        else
+                                perror(msg);
+
+                        return TTY_PARAM_ERROR;
+        }
+
+        /* parity */
+        switch (parity) {
+                case PARITY_NONE:
+                        break;
+                case PARITY_EVEN:
+                        tty_setting.c_cflag |= PARENB;
+                        break;
+                case PARITY_ODD:
+                        tty_setting.c_cflag |= PARENB | PARODD;
+                        break;
+                default:
+
+                        fprintf( stderr, "Default1\n") ;
+                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity)  0)
+                                perror(NULL);
+                        else
+                                perror(msg);
+
+                        return TTY_PARAM_ERROR;
+        }
+
+        /* stop_bits */
+        switch (stop_bits) {
+                case 1:
+                        break;
+                case 2:
+                        tty_setting.c_cflag |= CSTOPB;
+                        break;
+                default:
+                        fprintf( stderr, "Default2\n") ;
+                        if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits)  0)
+                                perror(NULL);
+                        else
+                                perror(msg);
+
+                        return TTY_PARAM_ERROR;
+        }
+
+#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
+       // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
+       // other than those specified by POSIX. The driver for the underlying serial hardware
+       // ultimately determines which baud rates can be used. This ioctl sets both the input
+       // and output speed.
+
+       speed_t speed = 14400; // Set 14400 baud
+    if (ioctl(fileDescriptor, IOSSIOSPEED, &speed) == -1)
+    {
+        printf("Error calling ioctl(..., IOSSIOSPEED, ...) %s - %s(%d).\n",
+            bsdPath, strerror(errno), errno);
+    }
+#endif
+
+    // Cause the new options to take effect immediately.
+    if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
+    {
+        printf("Error setting tty attributes %s - %s(%d).\n",
+            device, strerror(errno), errno);
+        goto error;
+    }
+
+    // To set the modem handshake lines, use the following ioctls.
+    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
+
+    if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
+    {
+        printf("Error asserting DTR %s - %s(%d).\n",
+            device, strerror(errno), errno);
+    }
+
+    if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
+    {
+        printf("Error clearing DTR %s - %s(%d).\n",
+            device, strerror(errno), errno);
+    }
+
+    handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
+    if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
+    // Set the modem lines depending on the bits set in handshake
+    {
+        printf("Error setting handshake lines %s - %s(%d).\n",
+            device, strerror(errno), errno);
+    }
+
+    // To read the state of the modem lines, use the following ioctl.
+    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
+
+    if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
+    // Store the state of the modem lines in handshake
+    {
+        printf("Error getting handshake lines %s - %s(%d).\n",
+            device, strerror(errno), errno);
+    }
+
+    printf("Handshake lines currently set to %d\n", handshake);
+
+#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
+       unsigned long mics = 1UL;
+
+       // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
+       // dequeue characters received by the hardware. Most applications don't need to set this value: if an
+       // app reads lines of characters, the app can't do anything until the line termination character has been
+       // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
+       // applications.
+
+       if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
+       {
+               // set latency to 1 microsecond
+        printf("Error setting read latency %s - %s(%d).\n",
+            device, strerror(errno), errno);
+        goto error;
+       }
+#endif
+
+   *fd = t_fd;
+  /* return success */
+  return TTY_OK;
+
+    // Failure path
+error:
+    if (t_fd != -1)
+    {
+        close(t_fd);
+    }
+
+    return TTY_PORT_FAILURE;
+}
+#else
 int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
 {
@@ -577,4 +846,8 @@
 #endif
 }
+// Unix - Linux version
+
+#endif
+
 
 int tty_disconnect(int fd)
@@ -644,2 +917,234 @@
    }	
 }
+
+/* return static string corresponding to the given property or light state */
+const char *
+pstateStr (IPState s)
+{
+        switch (s) {
+        case IPS_IDLE:  return ("Idle");
+        case IPS_OK:    return ("Ok");
+        case IPS_BUSY:  return ("Busy");
+        case IPS_ALERT: return ("Alert");
+        default:
+            fprintf (stderr, "Impossible IPState %d\n", s);
+            exit(1);
+        }
+}
+
+/* crack string into IPState.
+ * return 0 if ok, else -1
+ */
+int
+crackIPState (const char *str, IPState *ip)
+{
+             if (!strcmp (str, "Idle"))  *ip = IPS_IDLE;
+        else if (!strcmp (str, "Ok"))    *ip = IPS_OK;
+        else if (!strcmp (str, "Busy"))  *ip = IPS_BUSY;
+        else if (!strcmp (str, "Alert")) *ip = IPS_ALERT;
+        else return (-1);
+        return (0);
+}
+
+/* crack string into ISState.
+ * return 0 if ok, else -1
+ */
+int
+crackISState (const char *str, ISState *ip)
+{
+             if (!strcmp (str, "On"))  *ip = ISS_ON;
+        else if (!strcmp (str, "Off")) *ip = ISS_OFF;
+        else return (-1);
+        return (0);
+}
+
+int
+crackIPerm (const char *str, IPerm *ip)
+{
+             if (!strcmp (str, "rw"))  *ip = IP_RW;
+        else if (!strcmp (str, "ro")) *ip = IP_RO;
+        else if (!strcmp (str, "wo")) *ip = IP_WO;
+        else return (-1);
+        return (0);
+}
+
+int crackISRule (const char *str, ISRule *ip)
+{
+    if (!strcmp (str, "OneOfMany"))  *ip = ISR_1OFMANY;
+    else if (!strcmp (str, "AtMostOne")) *ip = ISR_ATMOST1;
+    else if (!strcmp (str, "AnyOfMany")) *ip = ISR_NOFMANY;
+    else return (-1);
+  return (0);
+}
+
+/* return static string corresponding to the given switch state */
+const char *
+sstateStr (ISState s)
+{
+        switch (s) {
+        case ISS_ON:  return ("On");
+        case ISS_OFF: return ("Off");
+        default:
+            fprintf (stderr, "Impossible ISState %d\n", s);
+        }
+}
+
+/* return static string corresponding to the given Rule */
+const char *
+ruleStr (ISRule r)
+{
+        switch (r) {
+        case ISR_1OFMANY: return ("OneOfMany");
+        case ISR_ATMOST1: return ("AtMostOne");
+        case ISR_NOFMANY: return ("AnyOfMany");
+        default:
+            fprintf (stderr, "Impossible ISRule %d\n", r);
+        }
+}
+
+/* return static string corresponding to the given IPerm */
+const char *
+permStr (IPerm p)
+{
+        switch (p) {
+        case IP_RO: return ("ro");
+        case IP_WO: return ("wo");
+        case IP_RW: return ("rw");
+        default:
+            fprintf (stderr, "Impossible IPerm %d\n", p);
+        }
+}
+
+/* print the boilerplate comment introducing xml */
+void
+xmlv1()
+{
+        printf ("<?xml version='1.0'?>\n");
+}
+
+/* pull out device and name attributes from root.
+ * return 0 if ok else -1 with reason in msg[].
+ */
+int
+crackDN (XMLEle *root, char **dev, char **name, char msg[])
+{
+        XMLAtt *ap;
+
+        ap = findXMLAtt (root, "device");
+        if (!ap) {
+            sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
+            return (-1);
+        }
+        *dev = valuXMLAtt(ap);
+
+        ap = findXMLAtt (root, "name");
+        if (!ap) {
+            sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
+            return (-1);
+        }
+        *name = valuXMLAtt(ap);
+
+        return (0);
+}
+
+/* find a member of an IText vector, else NULL */
+IText *
+IUFindText  (const ITextVectorProperty *tvp, const char *name)
+{
+        int i;
+
+        for (i = 0; i < tvp->ntp; i++)
+            if (strcmp (tvp->tp[i].name, name) == 0)
+                return (&tvp->tp[i]);
+        fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
+        return (NULL);
+}
+
+/* find a member of an INumber vector, else NULL */
+INumber *
+IUFindNumber(const INumberVectorProperty *nvp, const char *name)
+{
+        int i;
+
+        for (i = 0; i < nvp->nnp; i++)
+            if (strcmp (nvp->np[i].name, name) == 0)
+                return (&nvp->np[i]);
+        fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
+        return (NULL);
+}
+
+/* find a member of an ISwitch vector, else NULL */
+ISwitch *
+IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
+{
+        int i;
+
+        for (i = 0; i < svp->nsp; i++)
+            if (strcmp (svp->sp[i].name, name) == 0)
+                return (&svp->sp[i]);
+        fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
+        return (NULL);
+}
+
+/* find a member of an ILight vector, else NULL */
+ILight *
+IUFindLight(const ILightVectorProperty *lvp, const char *name)
+{
+        int i;
+
+        for (i = 0; i < lvp->nlp; i++)
+            if (strcmp (lvp->lp[i].name, name) == 0)
+                return (&lvp->lp[i]);
+        fprintf(stderr,"No ILight '%s' in %s.%s\n",name,lvp->device,lvp->name);
+        return (NULL);
+}
+
+/* find a member of an IBLOB vector, else NULL */
+IBLOB *
+IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name)
+{
+        int i;
+
+        for (i = 0; i < bvp->nbp; i++)
+            if (strcmp (bvp->bp[i].name, name) == 0)
+                return (&bvp->bp[i]);
+        fprintf(stderr,"No IBLOB '%s' in %s.%s\n",name,bvp->device,bvp->name);
+        return (NULL);
+}
+
+/* find an ON member of an ISwitch vector, else NULL.
+ * N.B. user must make sense of result with ISRule in mind.
+ */
+ISwitch *
+IUFindOnSwitch(const ISwitchVectorProperty *svp)
+{
+        int i;
+
+        for (i = 0; i < svp->nsp; i++)
+            if (svp->sp[i].s == ISS_ON)
+                return (&svp->sp[i]);
+        /*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
+        return (NULL);
+}
+
+/* Set all switches to off */
+void
+IUResetSwitch(ISwitchVectorProperty *svp)
+{
+  int i;
+
+  for (i = 0; i < svp->nsp; i++)
+    svp->sp[i].s = ISS_OFF;
+}
+
+/* save malloced copy of newtext in tp->text, reusing if not first time */
+void
+IUSaveText (IText *tp, const char *newtext)
+{
+        /* seed for realloc */
+        if (tp->text == NULL)
+            tp->text = malloc (1);
+
+        /* copy in fresh string */
+        tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
+}
Index: /BAORadio/libindi/libindi/libs/indicom.h
===================================================================
--- /BAORadio/libindi/libindi/libs/indicom.h	(revision 500)
+++ /BAORadio/libindi/libindi/libs/indicom.h	(revision 501)
@@ -48,5 +48,4 @@
 #define ERRMSG_SIZE 1024
 #define INDI_DEBUG
-
 
 extern const char * Direction[];
Index: /BAORadio/libindi/libindi/libs/lilxml.h
===================================================================
--- /BAORadio/libindi/libindi/libs/lilxml.h	(revision 500)
+++ /BAORadio/libindi/libindi/libs/lilxml.h	(revision 501)
@@ -248,9 +248,9 @@
 *   N.B. s must be at least as large as that reported by sprlXMLEle()+1.
 *   N.B. set level = 0 on first call.
-*   \return return length of resulting string (sans trailing \0)
+*   \return return length of resulting string (sans trailing @\0@)
 */
 extern int sprXMLEle (char *s, XMLEle *ep, int level);
 
-/** \brief return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing \0).
+/** \brief return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing @\0@).
 *   N.B. set level = 0 on first call.
 */
