PageRenderTime 56ms CodeModel.GetById 12ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 1ms

/elekIOaux/meteobox.c

http://github.com/Yniold/liftsrc
C | 353 lines | 228 code | 51 blank | 74 comment | 22 complexity | 44266d67bbc44f8de56086f8c6f6fc8d MD5 | raw file
  1// ============================================
  2// meteobox.c
  3// MeteoBox Control Thread
  4// ============================================
  5//
  6// $RCSfile: meteobox.c,v $ last changed on $Date: 2007/07/12 17:18:44 $ by $Author: rudolf $
  7//
  8// History:
  9//
 10// $Log: meteobox.c,v $
 11// Revision 1.7  2007/07/12 17:18:44  rudolf
 12// corrected include file order
 13//
 14// Revision 1.6  2007-03-08 14:01:22  rudolf
 15// cleaned up unused ports
 16//
 17// Revision 1.5  2007-03-07 21:13:54  rudolf
 18// startet work on ncurses based GUI
 19//
 20// Revision 1.4  2007-03-07 18:11:28  rudolf
 21// fixed nasty locking bug
 22//
 23// Revision 1.3  2007-03-05 20:48:09  rudolf
 24// added thread for collecting ship's data, more work on parser
 25//
 26// Revision 1.2  2007-03-04 19:28:41  rudolf
 27// added parsing for data into the right structure elements
 28//
 29// Revision 1.1  2007-03-04 13:41:59  rudolf
 30// created new server for auxilliary data like weather data, ships GPS etc
 31//
 32//
 33//
 34//
 35//
 36
 37//#define DEBUG_MUTEX
 38//#define DEBUG
 39//#define DEBUG_SETPOS
 40
 41#undef DEBUG
 42#undef DEBUG_SETPOS
 43#undef DEBUG_MUTEX
 44
 45#include <stdint.h>
 46#include <pthread.h>
 47#include <sys/socket.h>
 48#include <sys/types.h>
 49#include <errno.h>
 50#include <signal.h>
 51#include <ncurses.h>
 52
 53
 54#include "../include/elekGeneral.h"
 55#include "../include/elekIO.h"
 56#include "../include/elekIOPorts.h"
 57#include "../commTools/udptools.h"
 58
 59#include "meteobox.h"
 60
 61extern struct MessagePortType MessageOutPortList[];
 62extern bool bEnableGUI;
 63extern WINDOW* pStatusWin;
 64
 65enum OutPortListEnum
 66{
 67   // this list has to be coherent with MessageOutPortList
 68   ELEK_DEBUG_OUT,                 // port for outgoing messages to debug
 69     ELEK_MANUAL_OUT,                // reverse port for answers to eCmd
 70     ELEK_ELEKIO_AUX_MASTER_OUT,     // port for outgoing data packets from elekAux to master
 71     MAX_MESSAGE_OUTPORTS
 72};
 73
 74// Variables
 75//
 76typedef void Sigfunc (int);
 77volatile int iTryCounts = 0;
 78char aUDPBuffer[1024];
 79bool bGiveUp = false;
 80
 81// empty handler for connect() with timeout
 82static void connect_timeout_handler(int signo)
 83{
 84   extern struct MessagePortType MessageOutPortList[];
 85   SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : can't connect to MeteoBox for 2 seconds, still trying...");
 86   if(bEnableGUI)
 87     {
 88	wprintw(pStatusWin,"Can't connect to MeteoBox for 2000ms, still trying...\n");
 89	wrefresh(pStatusWin);
 90     }
 91   else
 92     printf("elekIOaux : can't connect to MeteoBox for 2000ms, still trying...\n\r");
 93   return;
 94};
 95
 96// empty handler for readl() with timeout
 97static void read_timeout_handler(int signo)
 98{
 99   extern struct MessagePortType MessageOutPortList[];
100
101   if(++iTryCounts < 11)
102     {
103
104	sprintf(aUDPBuffer,"elekIOaux : did not get any data from MeteoBox for %02d seconds, try # %02d...",iTryCounts*2, iTryCounts);
105	SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],aUDPBuffer);
106
107	if(bEnableGUI)
108	  {
109	     wprintw(pStatusWin,"Did not get any data from MeteoBox for %02d seconds, try # %02d...\n",iTryCounts*2, iTryCounts);
110	     wrefresh(pStatusWin);
111	  }
112	else
113	  printf("elekIOaux : did not get any data from MeteoBox for %02d seconds, try # %02d...\n\r",iTryCounts*2, iTryCounts);
114     }
115   else
116     {
117	bGiveUp = true;
118     };
119
120   return;
121};
122
123// the thread works on this structure
124//
125struct sMeteoBoxType sMeteoBoxThread =
126{
127   .iFD = -1,                      /* socket FD */
128     .Valid = 0,                /* signal if data is valid or not to main thread */
129
130     .dWindSpeed = 0,                /* Windspeed in m/s */
131     .uiWindDirection = 0,           /* 45° resolution */
132     .dRelHum = 0.0f,                /* 000.0 - 100.0 % */
133     .dAirTemp = 0.0f,               /* Temperature in degree celsius */
134     .dGasSensorVoltage = 0.0f       /* dirt sensor */
135};
136
137pthread_mutex_t mMeteoBoxMutex;
138
139// bind to socket and create the parser thread
140//
141int MeteoBoxInit(void)
142{
143   int iRetCode;
144   pthread_t ptMeteoBoxThread;
145
146   // init mutex before creating thread
147   pthread_mutex_init(&mMeteoBoxMutex,NULL);
148
149   iRetCode = pthread_create(&ptMeteoBoxThread, NULL, (void*)&MeteoBoxThreadFunc,(void*) &sMeteoBoxThread);
150   if(iRetCode > 0)
151     {
152	extern struct MessagePortType MessageOutPortList[];
153	SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : init MeteoBox successfull");
154	printf("In MeteoBoxInit(): pthread_create failed!\n\r");
155	return (1);
156     };
157
158   return(0);
159};
160
161// thread code
162//
163void MeteoBoxThreadFunc(void* pArgument)
164{
165   // buffer for one line
166   char aTCPBuffer[1024];
167
168   extern struct MessagePortType MessageOutPortList[];
169   int iRetVal;
170   Sigfunc *sigfunc;
171
172   char cTheChar;
173   char *pTheBuffer = aTCPBuffer;
174   int iNumChars;
175
176   // socket structure
177   struct sockaddr_in ServerAddress;
178
179   // shared structure
180   struct sMeteoBoxType *sStructure = (struct sMeteoBoxType *) pArgument;
181
182   while(1)
183     {
184	// try to connect till success
185	while(1)
186	  {
187
188	     // create SocketFD
189	     sStructure->iFD = socket(AF_INET, SOCK_STREAM, 0);
190	     memset(&ServerAddress,0, sizeof(ServerAddress));
191
192	     // fill out structure for connection to XPORT
193	     ServerAddress.sin_family = AF_INET;
194	     ServerAddress.sin_port = htons(XPORT_PORTNUMBER);
195	     ServerAddress.sin_addr.s_addr = inet_addr(XPORT_IP_ADDRESS);
196
197	     // save old handler and set new one
198	     sigfunc = signal(SIGALRM, connect_timeout_handler);
199
200	     // set timeout to 2 seconds
201	     alarm(2);
202
203	     // try connection to XPORT using a timeout
204	     if((iRetVal = connect(sStructure->iFD, (const struct sockaddr*)&ServerAddress, sizeof(ServerAddress))) < 0)
205	       {
206		  close(sStructure->iFD);
207		  if(errno == EINTR)
208		    errno = ETIMEDOUT;
209	       }
210	     else
211	       {
212		  break;
213	       };
214	  };
215	// we are connected now
216	// Turn off alarm
217	alarm(0);
218
219	// set handler for read timeout
220	sigfunc = signal(SIGALRM, read_timeout_handler);
221
222	if(iRetVal < 0)
223	  printf("%s\r\n",strerror(errno));
224	else
225	  {
226	     SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : Connected to XPORT on MeteoBox");
227	if(bEnableGUI)
228	  {
229	     wprintw(pStatusWin,"Connected to XPORT on MeteoBox\n");
230	     wrefresh(pStatusWin);
231	  }
232	else
233	     printf("elekIOaux : Connected to XPORT on MeteoBox\r\n");
234	  }
235	;
236
237	// read with timeout
238	while(bGiveUp == false)
239	  {
240	     sigfunc = signal(SIGALRM, read_timeout_handler);
241	     alarm(2);
242	     //	     printf("entering read()\r\n");
243
244	     if( (iRetVal = read(sStructure->iFD,&cTheChar,1)) < 0)
245	       {
246
247		  if(errno == EINTR)
248		    printf("elekIOaux : socket timeout\r\n");
249		  else
250		    printf("read() error\r\n");
251	       }
252	     // we got data in time
253	     else
254	       {
255		  alarm(0);
256		  iTryCounts = 0;
257		  //		  printf("Got a Byte\r\n");
258
259		  // check for start of buffer
260		  if(cTheChar == '\n')
261		    {
262		       pTheBuffer = aTCPBuffer;
263		       iNumChars = 0;
264		    }
265		  else
266		    // check for end of buffer
267		    if((cTheChar == '\r') && (iNumChars > 0))
268		      {
269			 aTCPBuffer[iNumChars] = 0;
270			 MeteoBoxParseBuffer(aTCPBuffer,iNumChars,sStructure);
271			 pTheBuffer = aTCPBuffer;
272			 iNumChars = 0;
273		      }
274		  else
275		    // store char
276		    if(iNumChars < 1024)
277		      {
278			 (*pTheBuffer) = cTheChar;
279			 pTheBuffer++;
280			 iNumChars++;
281		      }
282		  else
283		    {
284		       printf("Buffer overflow\n\r");
285		       pTheBuffer = aTCPBuffer;
286		       iNumChars = 0;
287		    };
288	       };
289	  };
290	printf("Trying to reconnect!\r\n");
291	close(sStructure->iFD);
292     };
293
294}
295
296void MeteoBoxParseBuffer(char* pBuffer, int iBuffLen, struct sMeteoBoxType* sDataStructure)
297{
298   char* pRetVal;
299   int iTokenNumber;
300   char* pContext;
301   //write(2,"Meteo: before lock\n\r",sizeof("Meteo: before lock\n\r"));
302   pthread_mutex_lock(&mMeteoBoxMutex);
303   //write(2,"Meteo: after lock\n\r",sizeof("Meteo: after lock\n\r"));
304
305   pRetVal = strtok_r(pBuffer,";",&pContext);
306
307   while(true)
308     {
309	if(pRetVal != NULL)
310	  {
311	     iTokenNumber++;
312	     //	     printf("Token %02d is '%s'\r\n",iTokenNumber,pRetVal);
313	     switch(iTokenNumber)
314	       {
315		case 3:
316		  sDataStructure->dWindSpeed = strtod(pRetVal,NULL);
317
318		case 9:
319		  sDataStructure->dAirTemp = strtod(pRetVal,NULL);
320
321		case 12:
322		  sDataStructure->dRelHum = strtod(pRetVal,NULL);
323
324		case 15:
325		  sDataStructure->uiWindDirection= atoi(pRetVal);
326
327		case 18:
328		  sDataStructure->dGasSensorVoltage = strtod(pRetVal,NULL);
329
330		default:
331		  break;
332	       };
333	     pRetVal=strtok_r(NULL,";",&pContext);
334	  }
335	else
336	  break;
337     };
338   sDataStructure->Valid.Field.MeteoBoxDataValid = 1;
339   //write(2,"Meteo: before unlock\n\r",sizeof("Meteo: before unlock\n\r"));
340   pthread_mutex_unlock(&mMeteoBoxMutex);
341   //write(2,"Meteo: after unlock\n\r",sizeof("Meteo: after unlock\n\r"));
342
343   if(gPlotData)
344     {
345
346	printf("Wind Speed: %05.3f m/s\r\n",sDataStructure->dWindSpeed);
347	printf("Air Temp:   %05.3f °C\r\n",sDataStructure->dAirTemp);
348	printf("Rel. Hum.:  %05.3f %\r\n",sDataStructure->dRelHum);
349	printf("Wind Dir.:  %03d °\r\n"   ,sDataStructure->uiWindDirection);
350	printf("Gas Sensor: %05.3f V\r\n\r\n",sDataStructure->dGasSensorVoltage);
351     }
352
353};