/*********************************************************************/
/* Program pro cteni teploty z teplomeru TM firmy Papouch            */
/* Mnoho diku Pavlovi a Jardovi za pomoc nezkusenemu programatorovi! */
/*********************************************************************/
/* Program je psan pro hp-ux, prekladac byl gcc.                     */
/* Co by se melo dodelat: kontrolovat navratove hodnoty pro pripadne */
/* hlaseni problemu.                                                 */
/*********************************************************************/
/* skript pro testovani vysledku; psano pro ksh                      */
/* PORT=/dev/tty0p7                                                  */
/* TM="/usr/local/bin/tm $PORT"                                      */
/* MEZ="+027.0C"                                                     */
/*                                                                   */
/* TEPLOTA=`$TM 2>&1`                                                */
/* NAVRAT=$?                                                         */
/* if [ "$NAVRAT" != 0 ] ; then                                      */
/*   echo "Chyba mereni: $TEPLOTA" # | mailx -s TEPLOTA adresa@nekde */
/*   exit                                                            */
/* fi                                                                */
/*                                                                   */
/* if [[ "$TEPLOTA" > "$MEZ" ]] ; then                               */
/*   echo "Teplota prekrocila limit $MEZ: $TEPLOTA" \                */
/*                      | mailx -s TEPLOTA adresa@nekde              */
/* fi                                                                */
/*                                                                   */
/**********************************************************************/
/* Poznamka: Na originalnim kabelu je pro napajeni pouzit pin DTR,
   ktery se prakticky neda ovladat. Program se pak vetsinou chova tak,
   ze vrati teplotu az na druhe poslani z cidla. Pri psani programu
   jsem pocital s tim, ze napajeni ovladam sam podle potreby (mam TM
   pripojeny pres redukci z konektoru 25 pin a napajeni je pres DSR
   (myslim :-) */

/* tohle zakomentovat, pokud se kompiluje na Linuxu */
#define HPUX

#include <stdio.h>
#include <sys/fcntl.h>
#include <unistd.h>
#ifdef HPUX
#include <sys/modem.h>
#include <termios.h>
#else
#include <asm/termios.h>
#endif
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/file.h>
#include <strings.h>
#define DEBUG 0

int serport;
int status, st2, oks, okg, n, navrat, ok, x;
struct timeval tv;
struct termios tp,tnew;
long baud;
fd_set rfd,wfd,efd;
char TEPLO[20];    /* buffer pro nactenou teplotu, s velkou  rezervou
							 i pro pripadne vicenasobne cteni */
char PORT[100];    /* jmeno portu (device) */


/***************************************************/
/* nastavim par vystupnich signalu na - napeti     */
/* -> vypnu teplomer                               */
/***************************************************/
int power_off() {
  status &= ~TIOCM_DSR;
  status &= ~TIOCM_DTR;
  status &= ~TIOCM_RTS;
  oks=ioctl(serport, TIOCMSET, &status);

#if DEBUG > 0
  printf("DSR set off: %x (%d .. %d) \n",status, oks, errno);
#endif

  okg=ioctl(serport, TIOCMGET, &st2);
#if DEBUG > 0
  printf("status: %x (%d .. %d) \n",st2, okg, errno);
#endif

  return oks;
}
/* end of power_off */

/***************************************************/
/* nastavim par vystupnich signalu na + napeti     */
/* -> zapnu teplomer                               */
/***************************************************/
int power_on() {
  status |= TIOCM_DSR;
  status |= TIOCM_DTR;
  status |= TIOCM_RTS;
  oks=ioctl(serport, TIOCMSET, &status);

#if DEBUG > 0
  printf("DSR set off: %x (%d .. %d) \n",status, oks, errno);
#endif

  okg=ioctl(serport, TIOCMGET, &st2);
#if DEBUG > 0
  printf("status: %x (%d .. %d) \n",st2, okg, errno);
#endif

  return oks;
}
/* end of power_on */

/*******************************************/
/* nastaveni parametru seriove komunikace  */
/*******************************************/
int set_port() {
  /* flush */
  /* flush prave zpusobuje precteni az druheho poslani teploty */
  tcflush(serport,TCIFLUSH);
  /* nastavim seriovy port na 9600, 8 bitu, 2 stopbity */
  if (tcgetattr(serport, &tp) < 0) {
		fprintf(stderr,"Couldn't get term attributes\n");
		return 2;
  }
  /* nastaveni ridicich priznaku */
  bzero(&tnew,sizeof(tnew));
  /* CS8 = 8 bitu; CLOCAL = ignorovat ridici signaly */
  baud=B9600;
  tnew.c_cflag = CS8|CLOCAL|CREAD|baud;

  /* nastaveni vystupnich priznaku */
  tnew.c_oflag = 0;
  /* ignore parity */
  tnew.c_iflag = IGNPAR;
  tnew.c_lflag = 0;

  tcflush(serport,TCIFLUSH);
  if (tcsetattr(serport, TCSANOW, &tnew) < 0) {
	  perror("Couldn't set term attributes");
	  return 2;
	}
	return 0;
}


/*************************************/
/* hlavni program ovladani teplomeru */
/*************************************/
int main (argc,argv)
int argc; char *argv[];
{
  if (argc < 2) {
	 printf ("Jako parametr mus¡ byt port (napr. /dev/tty0s1)!\n");
	 exit(-1);
  };

  strcpy(PORT, argv[1]);
#if DEBUG > 0
  printf("Parametru: %d\n",argc);
  printf("Parametr: %s\n", argv[1]);
  printf("Port: %s\n", PORT);
#endif

  /* default pro navratovou hodnotu - OK */
  navrat=0;

  /* otevru seriovy port */
  if ( (serport=open(PORT,O_RDONLY|O_NOCTTY)) == -1) {
	 fprintf(stderr,"CHYBA open - %s\n",PORT);
	 navrat=1;
	 exit (navrat);
  }
#if DEBUG > 0
  printf("SERPORT: %x\n",serport);
#endif

  /* nastavim parametry linky */
  ok=set_port();

  /* vypnu teplomer */
  ok=power_off();

  /* za 1 sekundu shozeneho napajeni by mel teplomer urcite chcipnout */
  /* (aby pak hned po nahozeni napajeni poslal teplotu a nemuselo se */
  /* pripadne cekat 10 vterin */
  sleep(1);

  /* vycistim a nastavim deskriptor pro port */
  FD_ZERO(&rfd);
  FD_SET(serport, &rfd);
  FD_ZERO(&wfd);
  FD_SET(serport, &wfd);
  FD_ZERO(&efd);
  FD_SET(serport, &efd);

  /* nastavim timout, pro jistotu dost velky  */
  tv.tv_sec = 12;
  tv.tv_usec = 0;

  /* zapnu teplomer */
  ok=power_on();

  /* pockame, az se neco nachysta na portu */
  switch ( n = select((1 + serport), &rfd, NULL, &efd, &tv ) ) {
	case -1: fprintf(stderr, "select error\n" );
				navrat=2;
				break;
	case  0: fprintf(stderr, "select timed out\n" );
				navrat=3;
				break;
	default: /* printf( "%d descriptors ready ...\n", n ); */
				if( FD_ISSET( serport, &rfd ) ) {
					/* puts( " -- serial descriptor has data pending" ); */
					/* neco nachystano je, ale pockame jeste chvilku,
						aby doslo urcite vsechno */
					usleep(200000);
					read(serport,&TEPLO,sizeof(TEPLO));
					/* HA, posila se nakonec ctrl-M, pryc se znaky pod mezeru */
					for (x=0; x <= strlen(TEPLO); x++) {
					  if (TEPLO[x] < ' ') TEPLO[x]=NULL;
					}
					puts(TEPLO);
				}
  }

  /* nastavim port do puvodniho stavu */
  if (tcsetattr(serport, TCSANOW, &tp) < 0) {
	  perror("Couldn't set term attributes");
	}

  /* opet vypnu teplomer */
  ok=power_off();
  /* zavru port */
  close(serport);
  /* a nazdar */
  exit (navrat);
}

