/* -------------------------------------------------------------------------- */
/* -           Protocol for LX200  command set telescope control            - */
/* -------------------------------------------------------------------------- */
/*                                                                            */
/* Copyright 2004-2012 John Kielkopf                                          */
/*                                                                            */
/* Distributed under the terms of the General Public License (see LICENSE)    */
/*                                                                            */
/* John Kielkopf (kielkopf@louisville.edu)                                    */
/*                                                                            */
/* Date: July 22, 2012                                                        */
/* Version: 6.0                                                               */
/*                                                                            */
/* History:                                                                   */ 
/*                                                                            */
/* February 17, 2002 -- Version 1.00                                          */ 
/*   These routines originated with lx200.c by                                */ 
/*   Ken Shouse (kshouse@econtrols.com)                                       */ 
/*     as modified by Carlos Guirao (cguirao@eso.org).                        */ 
/*                                                                            */
/* November 20, 2002 -- Version 1.10                                          */ 
/*   Thanks to Peter McCullough for a correction to the routine for           */ 
/*     parsing declination.                                                   */ 
/*                                                                            */
/* April 17, 2003 -- Version 2.00                                             */ 
/*   New functions implemented following Peter McCullough's use               */ 
/*     of protocol.c in his cltel program.                                    */ 
/*                                                                            */ 
/* New in version 2.00 --                                                     */ 
/*   Control focus, fan, reticle, derotator                                   */ 
/*   Optional max slew rate at compile time                                   */ 
/*   Function to set slew rate in degrees/second                              */ 
/*   Stop all NSEW motions                                                    */ 
/*   Set time at LX200                                                        */ 
/*                                                                            */ 
/* August 13, 2005 -- Version 2.10                                            */ 
/*   Updated for compatibility with new xmtel functions under development     */ 
/*                                                                            */
/* March 25, 2006 -- Version 3.0                                              */ 
/*   New structure for implementing pointing corrections                      */ 
/*                                                                            */
/* September 3, 2006 -- Version 3.0.4                                         */ 
/*   Added null functions for alignment with other protocols                  */ 
/*                                                                            */
/* September 12, 2008 -- Version 5.0                                          */ 
/*   Modified to work with INDI version of xmtel                              */ 
/*                                                                            */
/* June 26, 2010 -- Version 5.2.0                                             */ 
/*   Modified for compatibility with current xmtel                            */ 
/*   Some of the new xmtel functions remain unsupported with the LX200        */
/*   Added serial port option to header                                       */
/*                                                                            */
/* October 10, 2011 -- Version 5.3.0                                          */ 
/*   Added CenterGuide null function for compatibility with current xmtel     */ 
/*                                                                            */
/* February 27, 2012 -- Version 5.4.0                                         */ 
/*   Offset handling moved to pointing routine                                */ 
/*   Dynamic corrections added to pointing                                    */ 
/*                                                                            */
/* July 1, 2012 -- Version 6.0                                                */ 
/*   Leapsecond incremented in protocol.h                                     */ 



 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <math.h>
#include "protocol.h"

#define NULL_PTR(x) (x *)0

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif


/* System variables and prototypes */

/* Telescope and mounting commands that may be called externally */

/* Interface control */

void ConnectTel(void);
void DisconnectTel(void);
int  CheckConnectTel(void);

/* Slew and track control */

void SetRate(int newRate);
void StartSlew(int direction);
void StopSlew(int direction);
void StartTrack(void);
void CenterGuide(double centerra, double centerdec, 
  int raflag, int decflag, int pmodel);
void StopTrack(void);
void FullStop(void);

/* Coordinates and time */

void GetTel(double *telra, double *teldec, int pmodel);
int  GoToCoords(double newRA, double newDec, int pmodel);
int  CheckGoTo(double desRA, double desDec, int pmodel);

/* Slew limits */

int  GetSlewStatus(void);
int  SetLimits(int limits);
int  GetLimits(int *limits);


/* LX200 utilities -- not be used by XmTel */

double GetRA(void);
double GetDec(void);
void StopNSEW(void);
void SetRALimits(double limitLower, double limitHigher);
void SetDecLimits(double limitLower, double limitHigher);
void Reticle(int reticle);
int  SetSlewRate(int slewRate);

/* Instrumentation */

void Focus(int focuscmd, int focusspd);
void Rotate(int rotatecmd, int rotatespd);
void GetFocus(double *telfocus);
void GetRotate(double *telrotate);
void Fan(int fancmd);


/* External variables and code shared with XmTel */

extern double LSTNow(void);
extern double UTNow(void);
extern double offsetra, offsetdec;
extern double SiteLatitude;
extern char   telserial[32];

extern void PointingFromTel (double *telra1, double *teldec1, 
  double telra0, double teldec0, int pmodel);

extern void PointingToTel (double *telra0, double *teldec0, 
  double telra1, double teldec1, int pmodel);


/* LX200 local data */

static int focuscount;      /* Used to keep a focus position count */


/* Communications variables and routines for internal use */

static int TelPortFD;
static int TelConnectFlag = 0;

typedef fd_set telfds;

static int readn(int fd, char *ptr, int nbytes, int sec);
static int writen(int fd, char *ptr, int nbytes);
static int telstat(int fd,int sec,int usec);



/* End of prototype and variable definitions */


/* Report on telescope connection status */

int CheckConnectTel(void)
{
  if (TelConnectFlag == TRUE)
  {
    return TRUE;
  }
  else
  {
    return FALSE;
  }
}


/* Connect to the telescope serial interface */

void ConnectTel(void)
{
  struct termios tty;
  char returnStr[128];
  int numRead;

  if(TelConnectFlag != 0)
    return;

  /* Make the connection */

  TelPortFD = open(telserial,O_RDWR);
  if(TelPortFD == -1)
    return;

  tcgetattr(TelPortFD,&tty);
  cfsetospeed(&tty, (speed_t) B9600);
  cfsetispeed(&tty, (speed_t) B9600);
  tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
  tty.c_iflag =  IGNBRK;
  tty.c_lflag = 0;
  tty.c_oflag = 0;
  tty.c_cflag |= CLOCAL | CREAD;
  tty.c_cc[VMIN] = 1;
  tty.c_cc[VTIME] = 5;
  tty.c_iflag &= ~(IXON|IXOFF|IXANY);
  tty.c_cflag &= ~(PARENB | PARODD);
  tcsetattr(TelPortFD, TCSANOW, &tty);

  /* flush the input (read) buffer */
  tcflush(TelPortFD,TCIOFLUSH);

  /* send a # to clean up */
  writen(TelPortFD,"#",1);

  /* ask for local time to test connection */
  writen(TelPortFD,"#:GL#",5);
  numRead=readn(TelPortFD,returnStr,9,1);
  returnStr[numRead] = '\0';

  /* diagnostic test of local time */
  /* printf("LocalTime: %d read %s\n",numRead,returnStr); */

  if (numRead == 9) 
  {
    TelConnectFlag = 1;
  
/* Check precision on RA and toggle to high precision if needed */

    writen(TelPortFD,"#:GR#",5);
    numRead = readn(TelPortFD,returnStr,9,1);       
    if (numRead < 9)
    {
      writen(TelPortFD,"#:U#",4);
      usleep(250000.);
    }            
  }  
}

/* Set the speed for a motion command */

void SetRate(int newRate)
{
  if(newRate == SLEW) 
    writen(TelPortFD,"#:RS#",5);
  else if(newRate == FIND) 
    writen(TelPortFD,"#:RM#",5);
  else if(newRate == CENTER) 
    writen(TelPortFD,"#:RC#",5);
  else if(newRate == GUIDE) 
    writen(TelPortFD,"#:RG#",5);
}


void StartSlew(int direction)
{
  if(direction == NORTH)
    writen(TelPortFD,"#:Mn#",5);
  else if(direction == EAST)
    writen(TelPortFD,"#:Me#",5);
  else if(direction == SOUTH)
    writen(TelPortFD,"#:Ms#",5);
  else if(direction == WEST)
    writen(TelPortFD,"#:Mw#",5);
}

void StopSlew(int direction)
{
  if(direction == NORTH)
    writen(TelPortFD,"#:Qn#",5);
  else if(direction == EAST)
    writen(TelPortFD,"#:Qe#",5);
  else if(direction == SOUTH)
    writen(TelPortFD,"#:Qs#",5);
  else if(direction == WEST)
    writen(TelPortFD,"#:Qw#",5);
}

void DisconnectTel(void)
{
  /* printf("DisconnectTel\n"); */
  if(TelConnectFlag == 1)
    close(TelPortFD);
  TelConnectFlag = 0;
}


/* Read the telescope right ascension */

double GetRA(void)
{
  char  returnStr[10];
  double  raHr,raMin,raSec,returnRA;
  int  numRead;


  writen(TelPortFD,"#:GR#",5);
  numRead=readn(TelPortFD,returnStr,9,1);

        
/*   Most LX200's support high precision.                                     */
/*   ConnectTel tests the precision and tries to toggle to high precision.    */
/*   Low precision mode is not supported without modifying the following.     */    

  returnStr[8] = '\0';                                       
  sscanf(returnStr,"%lf:%lf:%lf",&raHr,&raMin,&raSec);                  
  returnRA = raHr + raMin/60.0 + raSec/3600.0;
  return returnRA;
}


/* Read the telescope declination */

double GetDec(void)
{
  char returnStr[10];
  double decDeg,decMin,decSec,returnDec;
  int numRead;


  writen(TelPortFD,"#:GD#",5);
  numRead=readn(TelPortFD,returnStr,10,1);

/*   Most LX200's support high precision, so                                  */
/*   ConnectTel tests the precision and tries to toggle to high precision.    */
/*   Low precision mode is not supported without modifying the following.     */    

/*   Since the LX200 may return something other than ':' as a delimiter,      */ 
/*   we parse each piece.                                                     */

/*   Thanks to cltel this now returns correct sign when decDeg = 0            */

  returnStr[3] = returnStr[6] = returnStr[9]='\0';  

  sscanf(returnStr,"%lf",&decDeg);                  
  sscanf(returnStr+4,"%lf:",&decMin);               
  sscanf(returnStr+7,"%lf",&decSec);
  returnDec = (double) fabs(decDeg) + decMin/60.0 + decSec/3600.0;
  if(returnStr[0] == '-') returnDec *= -1.;

  return returnDec;
}

/* Find the coordinates at which the telescope is pointing */

void GetTel(double *telra, double *teldec, int pmodel)
{
  double telra0, teldec0, telra1, teldec1;
 
  /* Read the telescope RA */
  
  telra0 = GetRA();

  /* Read the telescope Dec */
  
  teldec0 = GetDec();
  
  /* Correct the coordinates that are reported by the telescope */
  
  PointingFromTel(&telra1, &teldec1, telra0, teldec0, pmodel);

  /* Return corrected values */

  *telra=telra1;
  *teldec=teldec1;

  return;
}   

int GoToCoords(double newRA, double newDec, int pmodel)
{
  double telra0, telra1, teldec0, teldec1;
  int raHr, raMin, raSec;
  int decDeg, decMin, decSec;
  double dms, hms, ms;
  char outputStr[32], inputStr[2048];
  int returnVal;

  /* Where do we really want to go to? */
  
  telra1 = newRA;
  teldec1 = newDec;
  
  /* Where will the telescope point to make this happen? */
  
  PointingToTel(&telra0,&teldec0,telra1,teldec1,pmodel);
  
  /* Work with the telescope coordinates */
  
  newRA = telra0;
  newDec = teldec0;

  /* In high precision mode, we must send hh:mm:ss and dd:mm:ss */
  /* Allow for truncation if input is in seconds of arc */

  hms = newRA;
  hms = hms + 0.5/3600.;
  raHr = (int) hms;
  ms = hms - (double) raHr;
  ms = ms*60.;
  raMin = (int) ms;
  raSec = (int) 60.*(ms - (double) raMin);

  sprintf(outputStr,"#:Sr %02d:%02d:%02d#\n",raHr,raMin,raSec);
 
  writen(TelPortFD,outputStr,15);
  if (readn(TelPortFD,inputStr,1,1) != 1 ) exit(0); 
  if(inputStr[0] != '1')
  {
    fprintf(stderr,"Error setting object RA in GoToCoords!\n");
    fprintf(stderr,"Tried to send command string %s\n",outputStr);
    fprintf(stderr,"Received string %s\n",inputStr); 
  }

  if(newDec >= 0.0)
  {
    dms = newDec;
    dms = dms + 0.5/3600.;
    decDeg = (int) dms;
    ms = dms - (double) decDeg;
    ms = ms*60.;
    decMin = (int) ms;
    decSec = (int) 60.*(ms - (double) decMin);
    sprintf(outputStr,"#:Sd +%02d:%02d:%02d#\n",decDeg,decMin,decSec);
  }
  else
  {
    dms = -newDec;
    dms = dms + 0.5/3600.;
    decDeg = (int) dms;
    ms = dms - (double) decDeg;
    ms = ms*60.;
    decMin = (int) ms;
    decSec = (int) 60.*(ms - (double) decMin);
    sprintf(outputStr,"#:Sd -%02d:%02d:%02d#\n",decDeg,decMin,decSec);
  }


  writen(TelPortFD,outputStr,16);
  if (readn(TelPortFD,inputStr,1,1) != 1 ) 
  {
    DisconnectTel();
    return -1;
  }

  if(inputStr[0] != '1') 
  {
    fprintf(stderr,"Error setting object Dec in GoToCoords!\n");
    fprintf(stderr,"Tried to send command string %s\n",outputStr);
    fprintf(stderr,"Received string %s\n",inputStr);
  }

  writen(TelPortFD,"#:MS#",5);
  if (readn(TelPortFD,inputStr,1,5) != 1 ) 
  {
    DisconnectTel();
    return -1;
  }

  switch(inputStr[0]) 
  {
    case '0':
      return 0;
      break;
    case '1':
      returnVal = 1;
      fprintf(stderr,"Object is below horizon in GoToCoords.\n");
      break;
    case '2':
      returnVal = 2;
      fprintf(stderr,"Declination is above upper limit in GoToCoords.\n");
      break;
    default:
      fprintf(stderr,"Unexpected return from command #:MS#\n");
      return -1;
      break;
  }

  /* Look for '#' */
  
  for (;;) 
  {
    if ( readn(TelPortFD,inputStr,1,1) ) 
    {
      if (inputStr[0] == '#') break;
    }
    else 
    fprintf(stderr,"No acknowledgement from telescope after GoToCoords.\n");
    return -1;
  }
  return returnVal;
}

/* Test whether the destination was reached */

int CheckGoTo(double desRA, double desDec, int pmodel)
{  
  double telra0, telra1, teldec0, teldec1;
  double errorRA, errorDec, nowRA, nowDec;
        
  /* Where do we really want to go to? */
  
  telra1 = desRA;
  teldec1 = desDec;
  
  /* Where will the telescope point to make this happen? */
  
  PointingToTel(&telra0,&teldec0,telra1,teldec1,pmodel);
  
  /* Work with the telescope coordinates */
  
  desRA = telra0;
  desDec = teldec0;

  nowRA=GetRA();
  errorRA = nowRA - desRA;
  nowDec=GetDec();
  errorDec = nowDec - desDec;

  /* For 2 minute of arc precision */
  /*if( fabs(raError) > 1.0/(15.0*30.0) || fabs(decError) > 1.0/30.0)*/

  /* For 6 minute of arc precision */
  if( fabs(errorRA) > (0.1/15.) || fabs(errorDec) > 0.1)
  {
    return (0);
  }
  else
  {
    return (1);
  }  
}


/* Set lower and upper RA limits to protect hardware */

void SetRALimits(double limitLower, double limitHigher)
{

}


/* Set lower and upper dec limits to protect hardware */

void SetDecLimits(double limitLower, double limitHigher)
{
  int min, max;
  char outputStr[32], inputStr[2048];

  min = (int) limitLower;
  max = (int) limitHigher;

  sprintf(outputStr,"#:So %02d#\n",min);
  writen(TelPortFD,outputStr,9);

  if (readn(TelPortFD,inputStr,1,1) != 1 ) 
  {
    fprintf(stderr,"Unable to set Dec lower limit\n");
  }  

  sprintf(outputStr,"#:Sh %02d#\n",max);
  writen(TelPortFD,outputStr,8);
  if (readn(TelPortFD,inputStr,1,1) != 1 ) 
  {
    fprintf(stderr,"Unable to set Dec upper limit\n");
  }  
}


/* Set slew speed */

int SetSlewRate(int slewRate)
{
  char outputStr[32], inputStr[2048];
  if(slewRate > 1 && slewRate <= 4)
    {
    sprintf(outputStr,"#:Sw %1d#\n",slewRate);
    writen(TelPortFD,outputStr,8);
    if (readn(TelPortFD,inputStr,1,1) != 1 )
      fprintf(stderr,"Error: no response to set Slew Rate to %1d deg/sec.\n",slewRate);
    else
      {
      printf("Slew Rate set to %1d deg/sec\n",slewRate);
      return 1;
      }
    }

  printf("Invalid Slew Rate: %1d deg/sec, must be 2 to 4 deg/sec \n",slewRate);
  return 0;
}



/* Stop all motion */

void StopNSEW(void)
{
  writen(TelPortFD,"#:Qn#",5);
  writen(TelPortFD,"#:Qe#",5);
  writen(TelPortFD,"#:Qs#",5);
  writen(TelPortFD,"#:Qw#",5);
}


/* Run the focus using focuscmd */
/* Unlike most focus protocols for xmtel this one uses the drive controller */
/* The LX200 has fast and slow defined, so we have only two states */
/* Focus count is maintained by timing because the LX200 does not encode focus */

void Focus(int focuscmd, int focusspd)
{
  static int focusflag;
  static double focustime;

  if ( focuscmd == FOCUSCMDOUT ) 
  {
    focusflag = 1;
    focustime = UTNow();
    
    if ( focusspd > FOCUSSPD1 )
    {
      writen(TelPortFD,"#:FF#",5); 
    }
    else
    {
      writen(TelPortFD,"#:FS#",5);
    } 
       
    writen(TelPortFD,"#:F+#",5);
    return;
  }
  
  if ( focuscmd == FOCUSCMDIN )
  {
    focusflag = -1;
    focustime = UTNow();

    if ( focusspd > FOCUSSPD1 )
    {
      writen(TelPortFD,"#:FF#",5); 
    }
    else
    {
      writen(TelPortFD,"#:FS#",5);
    }
    
    writen(TelPortFD,"#:F-#",5);
    return;
  }  
    
  if ( focuscmd == FOCUSCMDOFF ) 
  {  
    if (focusflag != 0)
    {

      /* Focus is in motion so we note the time and then stop it */
      /* Keep track of count as number of seconds at slowest speed */
    
      focustime = UTNow() - focustime;
 
      /* Send the command */  
      writen(TelPortFD,"#:F0#",5) ;
    
      /* Just in case the UT clock rolled over one day while focusing */
      /* Try to trap the error but ...                                */
      /*   for very short focustime roundoff error may give negative  */
      /*   values instead of zero.  We trap those cases.              */
    
      if ( focustime < 0. )
      {
        if ( focustime < -23.9 )
        {
          focustime = focustime + 24.;
        }
        focustime = 0.;
      }
    
      /* Count time in tenths of seconds to get the focus change */
      /* This is to give more feedback to the observer but */
      /* UTNow does not pick up fractions of a second so least count is 10 */
    
      focustime = focustime*36000.;

      if ( focusflag == -1 )
      {
        focuscount = focuscount - focusspd * ( (int) focustime);
      }
      if ( focusflag == 1 )
      {
        focuscount = focuscount + focusspd * ( (int) focustime);
      }
      focusflag = 0;
    }
  
    if ( focusflag == 0 )
    {
    
      /* Focus motion is already stopped so there is nothing to do */
    }
  }    
}


/* Adjust the rotation */
/* LX200 rotator compensates for sidereal motion in an alt-az mounting */

void Rotate(int rotatecmd, int rotatespd)
{
  if ( rotatecmd != ROTATECMDOFF) 
  {
    if ( rotatespd == ROTATESPDSIDEREAL )
    {
      writen(TelPortFD,"#:r+#",5);
    }
  }
  else if ( rotatecmd == ROTATECMDOFF ) 
  {
    writen(TelPortFD,"#:r-#",5);
  }
  else
  {
    fprintf(stderr,"Unsupported rotation request for LX200.\n");
  }  
}

/* Control the fan */
/* LX200 fan has only one speed */

void Fan(int fancmd)
{
  if ( fancmd != FANCMDOFF ) 
  {
    writen(TelPortFD,"#:f+#",5);
  }
  else if ( fancmd == FANCMDOFF ) 
  {
    writen(TelPortFD,"#:f-#",5);
  }
}

/* Control the reticle function using predefined values */
/* XmTel does not use this */

void Reticle(int reticle)
{

#define BRIGHTER        16  /* increase */
#define DIMMER          8   /* decrease */
#define BLINK0          0   /* no blinking */ 
#define BLINK1          1   /* blink rate 1 */
#define BLINK2          2   /* blink rate 2 */
#define BLINK3          4   /* blink rate 3 */
    
  if ( reticle == BRIGHTER) writen(TelPortFD,"#:B+#",5);
  else if ( reticle == DIMMER ) writen(TelPortFD,"#:B-#",5);
  else if ( reticle == BLINK0 ) writen(TelPortFD,"#:B0#",5);  
  else if ( reticle == BLINK1 ) writen(TelPortFD,"#:B1#",5);     
  else if ( reticle == BLINK2 ) writen(TelPortFD,"#:B2#",5); 
  else if ( reticle == BLINK3 ) writen(TelPortFD,"#:B3#",5);
}

/* Tracking on/off utilities */


/* Start tracking if it is not on */

void StartTrack(void)
{
}


/* Use high resolution encoder to improve tracking */

void CenterGuide(double centerra, double centerdec, 
  int raflag, int decflag, int pmodel)
{
}


/* Stop tracking if it is on */

void StopTrack(void)
{
}


/* Stop all motion */

void FullStop(void)
{
}


/* Serial port utilities */

static int writen(fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
  int nleft, nwritten;
  nleft = nbytes;
  while (nleft > 0) 
  {
    nwritten = write (fd, ptr, nleft);
    if (nwritten <=0 ) break;
    nleft -= nwritten;
    ptr += nwritten;
  }
  return (nbytes - nleft);
}

static int readn(fd, ptr, nbytes, sec)
int fd;
char *ptr;
int nbytes;
int sec;
{
  int stat;
  int nleft, nread;
  nleft = nbytes;
  while (nleft > 0) 
  {
    stat = telstat(fd,sec,0);
    if (stat <=  0 ) break;
    nread  = read (fd, ptr, nleft);
    /* printf("readn: %d read\n", nread); */
    if (nread <= 0)  break;
    nleft -= nread;
    ptr += nread;
  }
  return (nbytes - nleft);
}

/*
 * Examines the read status of a file descriptor.
 * The timeout (sec, usec) specifies a maximum interval to
 * wait for data to be available in the descriptor.
 * To effect a poll, the timeout (sec, usec) should be 0.
 * Returns non-negative value on data available.
 * 0 indicates that the time limit referred by timeout expired.
 * On failure, it returns -1 and errno is set to indicate the
 * error.
 */
 
static int telstat(fd,sec,usec)
register int fd, sec, usec;
{
  int ret;
  int width;
  struct timeval timeout;
  telfds readfds;

  memset((char *)&readfds,0,sizeof(readfds));
  FD_SET(fd, &readfds);
  width = fd+1;
  timeout.tv_sec = sec;
  timeout.tv_usec = usec;
  ret = select(width,&readfds,NULL_PTR(telfds),NULL_PTR(telfds),&timeout);
  return(ret);
}


/* LX200 unsupported functions */

/* Return a flag indicating whether a slew is now in progress */

int GetSlewStatus(void)
{
  /* Always return a no-slew state */
  
  return (0);
}

/* Set slew limits control off or on */

int SetLimits(int limits)
{
  return (0);
}

/* Get status of slew limits control */

int GetLimits(int *limits)
{
  *limits = 0;
  return (0);
}


/* Control the dew heater */

void Heater(int heatercmd)
{
}


/* Report the focus  setting */

void GetFocus(double *telfocus)
{ 
  *telfocus = (double) focuscount;
}

 
/* Report the rotation setting */

void GetRotate(double *telrotate)
{
}

/* Report the temperature */

void GetTemperature(double *teltemperature)
{
}
