diff options
Diffstat (limited to 'kstars/kstars/indi/temmadriver.c')
-rw-r--r-- | kstars/kstars/indi/temmadriver.c | 1000 |
1 files changed, 1000 insertions, 0 deletions
diff --git a/kstars/kstars/indi/temmadriver.c b/kstars/kstars/indi/temmadriver.c new file mode 100644 index 00000000..55464493 --- /dev/null +++ b/kstars/kstars/indi/temmadriver.c @@ -0,0 +1,1000 @@ +#if 0 + Temma INDI driver + Copyright (C) 2004 Francois Meyer (dulle @ free.fr) + Remi Petitdemange for the temma protocol + Reference site is http://dulle.free.fr/alidade/indi.php + + 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 <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> +#include <time.h> + +#include "indicom.h" +#include "indidevapi.h" +#include "eventloop.h" +#include "indicom.h" +#include "temmadriver.h" + + + char errormes[][128]={ + "I/O Timeout", + "Error reading from io port", + "Error writing to io port", + "Unrecognized message" + }; + +char answer[32]; +int fd; +int read_ret, write_ret; +unsigned char buffer[256]; +unsigned char buffer2[256]; + + +#if 1 +/* Initlization routine */ +static void mountInit() +{ + static int inited; /* set once mountInit is called */ + + if (inited) + return; + + /* setting default comm port */ + PortT->text = realloc(PortT->text, 10); + TemmaNoteT[0].text = realloc( TemmaNoteT[0].text, 64); + TemmaNoteT[1].text = realloc( TemmaNoteT[1].text, 64); + + if (!PortT->text || !TemmaNoteT[0].text || !TemmaNoteT[1].text){ + fprintf(stderr,"Memory allocation error"); + return; + } + strcpy(PortT->text, "/dev/ttyS0"); + strcpy(TemmaNoteT[0].text, "Experimental Driver"); + strcpy(TemmaNoteT[1].text, "http://dulle.free.fr/alidade/indi.php"); + + inited = 1; +} +#endif + +void ISGetProperties (const char *dev) { + if (dev && strcmp (mydev, dev)) + return; + + mountInit(); + + IDDefSwitch (&powSw, NULL); + IDDefNumber (&eqTemma, NULL); + IDDefNumber (&eqNum, NULL); + IDDefSwitch (&OnCoordSetSw, NULL); + IDDefSwitch (&abortSlewSw, NULL); + IDDefText (&TemmaNoteTP, NULL); + IDDefSwitch (&RAmotorSw, NULL); + IDDefSwitch (&trackmodeSw, NULL); + IDDefText (&Port, NULL); + IDDefText (&TemmaVersion, NULL); + IDDefNumber (&Time, NULL); + IDDefNumber (&SDTime, NULL); + IDDefNumber (&cometNum, NULL); + IDDefNumber (&geoNum, NULL); +} + +void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n) +{ + dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n; +} + +void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) { + /*IText *tp;*/ + + if (strcmp (dev, mydev)) + return; + + if (!strcmp (name, Port.name)) { + IUSaveText(PortT, texts[0]); + Port.s = IPS_OK; + IDSetText (&Port, NULL); + } + return; +} + +/* client is sending us a new value for a Numeric vector property */ +void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) { + /* ignore if not ours */ + if (strcmp (dev, mydev)) + return; + + if (!strcmp (name, eqNum.name)) { + /* new equatorial target coords */ + /*double newra = 0, newdec = 0;*/ + int i, nset; + + /* Check power, if it is off, then return */ + if (power[0].s != ISS_ON) + { + eqNum.s = IPS_IDLE; + IDSetNumber(&eqNum, "Power is off"); + return; + } + + for (nset = i = 0; i < n; i++) { + /* Find numbers with the passed names in the eqNum property */ + INumber *eqp = IUFindNumber (&eqNum, names[i]); + + /* If the number found is Right ascension (eq[0]) then process it */ + if (eqp == &eq[0]) + { + currentRA = (values[i]); + nset += currentRA >= 0 && currentRA <= 24; + } + /* Otherwise, if the number found is Declination (eq[1]) then process it */ + else if (eqp == &eq[1]) { + currentDec = (values[i]); + nset += currentDec >= -90 && currentDec <= 90; + } + } /* end for */ + + /* Did we process the two numbers? */ + if (nset == 2) { + /*char r[32], d[32];*/ + + /* Set the mount state to BUSY */ + eqNum.s = IPS_BUSY; + + if (SLEWSW==ISS_ON || TRACKSW==ISS_ON){ + IDSetNumber(&eqNum, "Moving to RA Dec %f %f", currentRA, + currentDec); + do_TemmaGOTO(); + } + + if (SYNCSW==ISS_ON){ + IDSetNumber(&eqNum, "Syncing to RA Dec %f %f", currentRA, currentDec); + set_TemmaCurrentpos(); + } + eqNum.s = IPS_OK; + IDSetNumber(&eqNum, "Synced"); + } + /* We didn't process the two number correctly, report an error */ + else { + /* Set property state to idle */ + eqNum.s = IPS_IDLE; + + IDSetNumber(&eqNum, "RA or Dec absent or bogus."); + } + return; + } +} + +/* client is sending us a new value for a Switch property */ +void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n) +{ + ISwitch *sp; + + /* ignore if not ours */ + if (strcmp (dev, mydev)) + return; + + if (!strcmp (name, powSw.name)) { + sp = IUFindSwitch (&powSw, names[0]); + if (!sp) + return; + + fprintf(stderr,"new state %s\n",names[0]); + + sp->s = states[0]; + if (!strcmp(names[0],"CONNECT")) { + connectMount(); + } + if (!strcmp(names[0],"DISCONNECT")) { + disconnectMount(); + } + } + + if (!strcmp (name, abortSlewSw.name)) { + if (POWSW){ + TemmaabortSlew(); + IDSetSwitch (&abortSlewSw, "Abort slew"); + } + else { + IDSetSwitch (&abortSlewSw, "Power is off"); + } + } + + if (!strcmp (name, RAmotorSw.name)) { + if (POWSW){ + sp = IUFindSwitch (&RAmotorSw, names[0]); + if (!sp) + return; + + fprintf(stderr,"new state %s\n",names[0]); + + sp->s = states[0]; + + RAmotorSw.s = IPS_BUSY; + if (!strcmp(names[0],"RUN")) { + set_TemmaStandbyState(0); + } + + if (!strcmp(names[0],"STOP")) { + set_TemmaStandbyState(1); + } + + if(get_TemmaStandbyState(buffer)){ + RAmotorSw.s = IPS_IDLE; + IDSetSwitch (&RAmotorSw, "Error writing to port"); + return; + } + } + else { + IDSetSwitch (&RAmotorSw, "Power is off"); + } + } + + if (!strcmp (name, OnCoordSetSw.name)) { + if (POWSW){ + IUResetSwitches(&OnCoordSetSw); + sp = IUFindSwitch (&OnCoordSetSw, names[0]); + if (!sp) + return; + + fprintf(stderr,"new state %s\n",names[0]); + + sp->s = states[0]; + + IUResetSwitches(&OnCoordSetSw); + IUUpdateSwitches(&OnCoordSetSw, states, names, n); + /* currentSet = getOnSwitch(&OnCoordSetSw); */ + OnCoordSetSw.s = IPS_OK; + IDSetSwitch(&OnCoordSetSw, NULL); + } + else { + IDSetSwitch (&OnCoordSetSw, "Power is off"); + } + } +} + +double calcLST(char *strlst){ + time_t computertime; + struct tm gmt; + double jd, gmst; + double lst; + /*int a,b;*/ + + time(&computertime); + gmtime_r(&computertime, &gmt); + gmt.tm_mon+=1; + gmt.tm_year+=1900; + currentUTC=(double)gmt.tm_hour+(double)gmt.tm_min/60+(double)gmt.tm_sec/3600; + + jd=UTtoJD(&gmt); + gmst=JDtoGMST(jd); + + lst=(gmst-longitude)/15; + + lst=(lst/24-(int)(lst/24))*24; + + if(lst>=24) + lst-=24; + sprintf(strlst,"%.2d%.2d%.2d", (int)lst, + ((int)(lst*60))%60, + ((int)(lst*3600))%60); + currentLST=lst; + IDSetNumber (&SDTime, NULL); + IDSetNumber (&Time, NULL); + + return 0; +} + +#if 1 +/* update the mount over time */ +void readMountcurrentpos (void *p) +{ + char result[32]; + + if(POWSW){ + get_TemmaCurrentpos(result); + calcLST(result); + + /* This is a temporary workaround to allow + clients with only one eq property to work */ + currentRA=temmaRA; + currentDec=temmaDec; + + /* again */ + IEAddTimer (POLLMS, readMountcurrentpos, NULL); + } +} +#endif + +static void connectMount () { + fprintf(stderr,"opening mount port %s\n",PortT->text); + if (power[0].s == ISS_ON){ + if (Port.s != IPS_OK){ + powSw.s = IPS_IDLE; + power[0].s = ISS_OFF; + + IDSetSwitch (&powSw, "Port not set."); + return; + } + else { + if (TemmaConnect(PortT->text)==0){ + IDSetText (&Port, "Port is opened."); + if( !get_TemmaVERSION(buffer)){ + powSw.s = IPS_OK; + power[0].s = ISS_ON; + power[1].s = ISS_OFF; + snprintf(buffer2,sizeof( buffer2 ),"%s",buffer+4); + + IDSetText(&TemmaVersion , "Temma version set"); + TemmaVersionT->text = realloc(TemmaVersionT->text, strlen(buffer2)+1); + if (!TemmaVersionT->text){ + fprintf(stderr,"Memory allocation error"); + return; + } + IDSetSwitch (&powSw, "Mount is ready"); + IDSetSwitch (&powSw, VERSION); + + strcpy(TemmaVersionT->text, buffer2); + TemmaVersion.s = IPS_OK; + IDSetText (&TemmaVersion, NULL); + IDLog("%s", buffer2); + /* start timer to read mount coords */ + IEAddTimer (POLLMS, readMountcurrentpos, NULL); + } + else { + powSw.s = IPS_IDLE; + power[0].s = ISS_OFF; + power[1].s = ISS_ON; + IDSetText(&Port , "Com error"); + IDSetSwitch (&powSw, "Port not set."); + } + + if(get_TemmaStandbyState(answer)){ + IDSetSwitch (&RAmotorSw, "Error writing to port"); + return; + } + } + else { + powSw.s = IPS_IDLE; + power[0].s = ISS_OFF; + power[1].s = ISS_ON; + + IDSetSwitch (&powSw, "Failed to open port."); + } + } + } +} + +static void disconnectMount () { + fprintf(stderr,"closing mount port %s\n",PortT->text); + if (power[1].s == ISS_ON){ + if (Port.s != IPS_OK){ + powSw.s = IPS_IDLE; + power[0].s = ISS_OFF; + + IDSetSwitch (&powSw, "Port not set."); + return; + } + else { + TemmaDisconnect(); + powSw.s = IPS_IDLE; + power[0].s = ISS_OFF; + + IDSetSwitch (&powSw, "Port is closed."); + } + } + else { + fprintf(stderr, "Already disconnected \n"); + } +} + +int TemmaConnect(const char *device) { + fprintf(stderr, "Connecting to device %s\n", device); + + if (openPort(device) < 0){ + fprintf(stderr, "Error connecting to device %s\n", device); + return -1; + } + else{ + return 0; + } +} + +int TemmaDisconnect() { + fprintf(stderr, "Disconnected.\n"); + close(fd); + + return 0; +} + +int set_CometTracking(int RArate, int DECrate){ +#if 0 + Set Comet Tracking + LM+/-99999,+/-9999 + RA : Adjust Sidereal time by seconds per Day + + DEC : Adjust DEC tracking by Minutes Per Day + valeur DEC min=-600 /max=+600 (+/-10 deg / jour) + + Example: + LM+120,+30 would slow the RA speed by 86164/86284 and + the Dec would track at 30 Minutes a day. + To stop tracking either send a LM0,0 (or a PS + sauf erreur on constate en faite l inverse en RA + retour Vsideral => LM0,0 ou LM+0,+0 +#endif + char local_buffer[16]; + + if (RArate<-21541){ + RArate=-21541; + } + + if (RArate>21541){ + RArate=21541; + } + + if (DECrate<-600){ + DECrate=-600; + } + + if (DECrate>600){ + DECrate=600; + } + + snprintf(local_buffer, sizeof( local_buffer ), "%+6d,%+5d", RArate, DECrate); + set_TemmaCometTracking(local_buffer); + + return 0; +} + +int TemmaabortSlew() { + if (portWrite("PS") < 0) + return -1; + + return 0; +} + +int do_TemmaGOTO() { + /* Temma Sync */ + char command[16]; + char sign; + double dec; + + calcLST(buffer); + set_TemmaLST(buffer); + + dec=fabs(currentDec); + if (currentDec>0){ + sign='+'; + } + else { + sign='-'; + } + + snprintf(buffer, sizeof(buffer),"%.2d%.2d%.2d%c%.2d%.2d%.1d", + (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign, + (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10); + fprintf(stderr,"Goto %s\n", buffer); + + snprintf(command,14,"P%s",buffer); + buffer[14]=0; + fprintf(stderr,"Goto command:%s\n", command); + portWrite(command); + + portRead(buffer,-1,TEMMA_TIMEOUT); + if(command[0]=='R'){ + return 0; + } + else + return -1; +} + +int extractRA(char *buf){ + int r,h,m,s; + /*double dra;*/ + + r=atoi(buf); + h=r/10000; + m=r/100-100*h; + s=(r%100)*.6; + temmaRA=((double)h+((double)m + (double)s/60)/60); + IDSetNumber (&eqTemma, NULL); + /* fprintf(stderr,"extractRA: %s %d %d %d %d %lf\n",buf,r,h,m,s,dra);*/ + return 0; +} + +int extractDEC(char *buf){ + int dec,d,m,s; + /*double ddec;*/ + + dec=atoi(buf+1); + d=dec/1000; + m=dec/10-100*d; + s=(dec%10)*6; + temmaDec=((double)d+((double)m + (double)s/60)/60); + if (*buf=='-') + temmaDec*=-1; + + IDSetNumber (&eqTemma, NULL); + + + /* fprintf(stderr,"extractDEC: %s %d %d %d %d %lf\n",buf,dec,d,m,s,ddec);*/ + return 0; +} + + +int get_TemmaCurrentpos(char *local_buffer){ + char buf[16]; + + if (portWrite("E") < 0) + return -1; + + if(portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS){ + if(strstr(local_buffer, "E")==local_buffer){ + strncpy(buf,local_buffer+1,6); + buf[6]=0; + extractRA(buf); + + strncpy(buf,local_buffer+7,6); + buf[6]=0; + extractDEC(buf); + return 0; + } + else { + return -1; + } + } + + return 0; +} + +int set_TemmaCurrentpos(void) { + /* Temma Sync */ + char buf[16], sign; + double dec; + + calcLST(buf); + set_TemmaLST(buf); + portWrite("Z"); + calcLST(buf); + set_TemmaLST(buf); + + dec=fabs(currentDec); + if (currentDec>0){ + sign='+'; + } + else { + sign='-'; + } + + sprintf(buffer,"%.2d%.2d%.2d%c%.2d%.2d%.1d", + (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign, + (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10); + fprintf(stderr,"sync to %s %f %f\n", buffer,currentRA,dec); + + snprintf(buf, sizeof(buf), "D%s",buffer); + buf[13]=0; + portWrite(buf); + *buffer=0; + + portRead(buffer,-1,TEMMA_TIMEOUT); + if(buffer[0]=='R'){ + return 0; + } + else{ + return -1; + } +} + +int do_TemmaSLEW(char mode){ + /*char command[16];*/ + + sprintf(buffer,"M%c",mode); /* see bit definition in Temmadriver.h */ + + if (portWrite(buffer) < 0) + return -1; + + return 0; +} + +int get_TemmaVERSION(char *local_buffer){ + int err; + + if ((err=portWrite("v")) < 0){ + return err; + } + + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "ver")==local_buffer){ + return 0; + } + else + return EREAD; +} + +int get_TemmaGOTOstatus(char *local_buffer){ + /* + 0 no ongoing goto + 1 ongoing Goto + -1 error + */ + if (portWrite("s") < 0) + return -1; + + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "s")==local_buffer){ + return 0; + } + else + return -1; +} + +int get_TemmaBOTHcorrspeed(char *local_buffer){ + if (portWrite("lg") < 0) + return -1; + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "lg")==local_buffer){ + return 0; + } + else + return -1; +} + +int get_TemmaDECcorrspeed(char *local_buffer){ + if (portWrite("lb") < 0) + return -1; + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "lb")==local_buffer){ + return 0; + } + else + return -1; +} + +int set_TemmaDECcorrspeed(char *local_buffer){ + char command[16]; + + snprintf(command, 4, "LB%s",local_buffer); + + if (portWrite(command) < 0) + return -1; + return 0; +} + +int get_TemmaRAcorrspeed(char *local_buffer){ + if (portWrite("la") < 0) + return -1; + + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "la")==local_buffer){ + return 0; + } + else + return -1; +} + +int set_TemmaRAcorrspeed(char *local_buffer){ + char command[16]; + + snprintf(command, 4,"LA%s",local_buffer); + + if (portWrite(command) < 0) + return -1; + return 0; +} + +int get_TemmaLatitude(char *local_buffer){ + if (portWrite("i") < 0) + return -1; + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(local_buffer[0]=='i'){ + return 0; + } + else + return -1; +} + +int set_TemmaLatitude(char *local_buffer){ + char command[16]; + double lat; + char sign; + + lat=fabs(latitude); + if (latitude>0){ + sign='+'; + } + else { + sign='-'; + } + + sprintf(command,"I%c%.2d%.2d%.1d", sign, + (int)lat, + (int)(lat*(double)60)%60, + ((int)(lat*(double)600))%10); + + if (portWrite(command) < 0) + return -1; + return 0; +} + +int get_TemmaLST(char *local_buffer){ + if (portWrite("g") < 0) + return -1; + + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(local_buffer[0]=='g'){ + return 0; + } + else + return -1; +} + + +int set_TemmaLST(char *local_buffer){ + char command[16]; + snprintf(command,7,"T%s",local_buffer); + + if (portWrite(command) < 0) + return -1; + return 0; +} + + +int get_TemmaCometTracking(char *local_buffer){ + if (portWrite("lm") < 0) + return -1; + portRead(local_buffer,-1,TEMMA_TIMEOUT); + if(strstr(local_buffer, "lm")==local_buffer){ + return 0; + } + else + return -1; +} + +int set_TemmaStandbyState(int on){ + if (on){ + return portWrite("STN-ON"); + } + else{ + return portWrite("STN-OFF"); + } + return 0; +} + +int get_TemmaStandbyState(unsigned char *local_buffer){ + int nb; + int status; + + if ((nb=portWrite("STN-COD")) < 0){ + IDSetSwitch (&RAmotorSw, "I/O error when asking RAmotor status"); + return -1; + } + + if((status=portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS)){ + if(strstr(local_buffer, "stn")==local_buffer){ + local_buffer[7]=0; + if (strstr(local_buffer,"on")){ /* stanby on */ + RAmotorSw.s = IPS_OK; + RAmotor[0].s = ISS_OFF; + RAmotor[1].s = ISS_ON; + IDSetSwitch (&RAmotorSw, "RA motor is off."); + } + else{ + if (strstr(local_buffer,"off")){ /* stanby off */ + RAmotorSw.s = IPS_OK; + RAmotor[0].s = ISS_ON; + RAmotor[1].s = ISS_OFF; + IDSetSwitch (&RAmotorSw, "RA motor is on."); + } + else { + RAmotorSw.s = IPS_OK; + IDSetSwitch (&RAmotorSw, "I/O error when getting RAmotor status"); + } + } + } + return 0; + } + if (status<=ETIMEOUT && status >=ECOMMAND){ + IDSetSwitch(&RAmotorSw, "%s", errormes[ETIMEOUT - status]); + } + + return -1; +} + +int set_TemmaCometTracking(char *local_buffer){ + char command[16]; + + snprintf(command,15,"LM%s",local_buffer); + if (portWrite(command) < 0) + return -1; + return 0; +} + +int set_TemmaSolarRate(void){ + if (portWrite("LK") < 0) + return -1; + return 0; +} + +int set_TemmaStellarRate(void){ + if (portWrite("LL") < 0) + return -1; + return 0; +} + + +int switch_Temmamountside(void){ + if (portWrite("PT") < 0) + return -1; + return 0; +} + +/********************************************************************** + * Comm + **********************************************************************/ + +int openPort(const char *portID) { + struct termios ttyOptions; + + if ( (fd = open(portID, O_RDWR)) == -1) + return -1; + memset(&ttyOptions, 0, sizeof(ttyOptions)); + tcgetattr(fd, &ttyOptions); + + /* 8 bit, enable read */ + ttyOptions.c_cflag |= CS8; + /* parity */ + ttyOptions.c_cflag |= PARENB; + ttyOptions.c_cflag &= ~PARODD; + ttyOptions.c_cflag &= ~CSTOPB; + ttyOptions.c_cflag |= CRTSCTS; + + /* set baud rate */ + cfsetispeed(&ttyOptions, B19200); + cfsetospeed(&ttyOptions, B19200); + + /* set input/output flags */ + ttyOptions.c_iflag = IGNBRK; + + /* Read at least one byte */ + ttyOptions.c_cc[VMIN] = 1; + ttyOptions.c_cc[VTIME] = 5; + + /* Misc. */ + ttyOptions.c_lflag = 0; + ttyOptions.c_oflag = 0; + + /* set attributes */ + tcsetattr(fd, TCSANOW, &ttyOptions); + + /* flush the channel */ + tcflush(fd, TCIOFLUSH); + return (fd); +} + +int portWrite(char * buf) { + int nbytes=strlen(buf); /*, totalBytesWritten;*/ + int bytesWritten = 0; + /*int retry=10;*/ + + bytesWritten = write(fd, buf, nbytes); + bytesWritten += write(fd, "\r\n", 2); + /*fprintf(stderr,"portwrite :%d octets %s\n", bytesWritten, buf);*/ + + if (bytesWritten!=nbytes+2){ + perror("write error: "); + IDLog("Error writing to port"); + return EWRITE; + } + return (bytesWritten); +} + +int portRead(char *buf, int nbytes, int timeout) { + /* + A very basic finite state machine monitors + the bytes read ; + state 0 : read regular bytes + state 1 : just read a \n, waiting for a \r + state 2 : read a \n and a \r, command is over. + + Not sure it is useful here but I use a more + sophisticated version of this with a GPS receiver + and it is robust and reliable + + We return a null terminated string. + */ + + int bytesRead = 0, state=0, /*i=0,*/ current=0; + /*int totalBytesRead = 0;*/ + int err; + + if ( (err = TemmareadOut(timeout)) ){ + switch (err){ + case ETIMEOUT: + IDLog("Error: timeout while reading"); + return err; + } + } + + while (read(fd,buf+bytesRead,1)==1){ + /* fprintf(stderr,"%c",buf[bytesRead]); */ + fflush(NULL); + switch (state) { + case 0: + if(buf[bytesRead]==13) + state=1; + break; + + case 1: + if(buf[bytesRead]==10) + state=2; + else + if(buf[bytesRead]==13) + state=1; + else + state=0; + break; + } + + ++current; + + if (state==2){ + /*process(buf);*/ + buf[bytesRead+1]=0; + state=current=0; + return SUCCESS; + } + + bytesRead=current; + } + return state; +} + +int TemmareadOut(int timeout) { + struct timeval tv; + fd_set readout; + int retval; + + FD_ZERO(&readout); + FD_SET(fd, &readout); + + /* wait for 'timeout' seconds */ + tv.tv_sec = timeout; + tv.tv_usec = 0; + + /* Wait till we have a change in the fd status */ + retval = select (fd+1, &readout, NULL, NULL, &tv); + + /* Return 0 on successful fd change */ + if (retval > 0) + return 0; + /* Return -1 due to an error */ + else if (retval == EREAD) + return retval; + /* Return -2 if time expires before anything interesting happens */ + else { + return ETIMEOUT; + } +} + |