PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/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. //#define DEBUG_MUTEX
  37. //#define DEBUG
  38. //#define DEBUG_SETPOS
  39. #undef DEBUG
  40. #undef DEBUG_SETPOS
  41. #undef DEBUG_MUTEX
  42. #include <stdint.h>
  43. #include <pthread.h>
  44. #include <sys/socket.h>
  45. #include <sys/types.h>
  46. #include <errno.h>
  47. #include <signal.h>
  48. #include <ncurses.h>
  49. #include "../include/elekGeneral.h"
  50. #include "../include/elekIO.h"
  51. #include "../include/elekIOPorts.h"
  52. #include "../commTools/udptools.h"
  53. #include "meteobox.h"
  54. extern struct MessagePortType MessageOutPortList[];
  55. extern bool bEnableGUI;
  56. extern WINDOW* pStatusWin;
  57. enum OutPortListEnum
  58. {
  59. // this list has to be coherent with MessageOutPortList
  60. ELEK_DEBUG_OUT, // port for outgoing messages to debug
  61. ELEK_MANUAL_OUT, // reverse port for answers to eCmd
  62. ELEK_ELEKIO_AUX_MASTER_OUT, // port for outgoing data packets from elekAux to master
  63. MAX_MESSAGE_OUTPORTS
  64. };
  65. // Variables
  66. //
  67. typedef void Sigfunc (int);
  68. volatile int iTryCounts = 0;
  69. char aUDPBuffer[1024];
  70. bool bGiveUp = false;
  71. // empty handler for connect() with timeout
  72. static void connect_timeout_handler(int signo)
  73. {
  74. extern struct MessagePortType MessageOutPortList[];
  75. SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : can't connect to MeteoBox for 2 seconds, still trying...");
  76. if(bEnableGUI)
  77. {
  78. wprintw(pStatusWin,"Can't connect to MeteoBox for 2000ms, still trying...\n");
  79. wrefresh(pStatusWin);
  80. }
  81. else
  82. printf("elekIOaux : can't connect to MeteoBox for 2000ms, still trying...\n\r");
  83. return;
  84. };
  85. // empty handler for readl() with timeout
  86. static void read_timeout_handler(int signo)
  87. {
  88. extern struct MessagePortType MessageOutPortList[];
  89. if(++iTryCounts < 11)
  90. {
  91. sprintf(aUDPBuffer,"elekIOaux : did not get any data from MeteoBox for %02d seconds, try # %02d...",iTryCounts*2, iTryCounts);
  92. SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],aUDPBuffer);
  93. if(bEnableGUI)
  94. {
  95. wprintw(pStatusWin,"Did not get any data from MeteoBox for %02d seconds, try # %02d...\n",iTryCounts*2, iTryCounts);
  96. wrefresh(pStatusWin);
  97. }
  98. else
  99. printf("elekIOaux : did not get any data from MeteoBox for %02d seconds, try # %02d...\n\r",iTryCounts*2, iTryCounts);
  100. }
  101. else
  102. {
  103. bGiveUp = true;
  104. };
  105. return;
  106. };
  107. // the thread works on this structure
  108. //
  109. struct sMeteoBoxType sMeteoBoxThread =
  110. {
  111. .iFD = -1, /* socket FD */
  112. .Valid = 0, /* signal if data is valid or not to main thread */
  113. .dWindSpeed = 0, /* Windspeed in m/s */
  114. .uiWindDirection = 0, /* 45° resolution */
  115. .dRelHum = 0.0f, /* 000.0 - 100.0 % */
  116. .dAirTemp = 0.0f, /* Temperature in degree celsius */
  117. .dGasSensorVoltage = 0.0f /* dirt sensor */
  118. };
  119. pthread_mutex_t mMeteoBoxMutex;
  120. // bind to socket and create the parser thread
  121. //
  122. int MeteoBoxInit(void)
  123. {
  124. int iRetCode;
  125. pthread_t ptMeteoBoxThread;
  126. // init mutex before creating thread
  127. pthread_mutex_init(&mMeteoBoxMutex,NULL);
  128. iRetCode = pthread_create(&ptMeteoBoxThread, NULL, (void*)&MeteoBoxThreadFunc,(void*) &sMeteoBoxThread);
  129. if(iRetCode > 0)
  130. {
  131. extern struct MessagePortType MessageOutPortList[];
  132. SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : init MeteoBox successfull");
  133. printf("In MeteoBoxInit(): pthread_create failed!\n\r");
  134. return (1);
  135. };
  136. return(0);
  137. };
  138. // thread code
  139. //
  140. void MeteoBoxThreadFunc(void* pArgument)
  141. {
  142. // buffer for one line
  143. char aTCPBuffer[1024];
  144. extern struct MessagePortType MessageOutPortList[];
  145. int iRetVal;
  146. Sigfunc *sigfunc;
  147. char cTheChar;
  148. char *pTheBuffer = aTCPBuffer;
  149. int iNumChars;
  150. // socket structure
  151. struct sockaddr_in ServerAddress;
  152. // shared structure
  153. struct sMeteoBoxType *sStructure = (struct sMeteoBoxType *) pArgument;
  154. while(1)
  155. {
  156. // try to connect till success
  157. while(1)
  158. {
  159. // create SocketFD
  160. sStructure->iFD = socket(AF_INET, SOCK_STREAM, 0);
  161. memset(&ServerAddress,0, sizeof(ServerAddress));
  162. // fill out structure for connection to XPORT
  163. ServerAddress.sin_family = AF_INET;
  164. ServerAddress.sin_port = htons(XPORT_PORTNUMBER);
  165. ServerAddress.sin_addr.s_addr = inet_addr(XPORT_IP_ADDRESS);
  166. // save old handler and set new one
  167. sigfunc = signal(SIGALRM, connect_timeout_handler);
  168. // set timeout to 2 seconds
  169. alarm(2);
  170. // try connection to XPORT using a timeout
  171. if((iRetVal = connect(sStructure->iFD, (const struct sockaddr*)&ServerAddress, sizeof(ServerAddress))) < 0)
  172. {
  173. close(sStructure->iFD);
  174. if(errno == EINTR)
  175. errno = ETIMEDOUT;
  176. }
  177. else
  178. {
  179. break;
  180. };
  181. };
  182. // we are connected now
  183. // Turn off alarm
  184. alarm(0);
  185. // set handler for read timeout
  186. sigfunc = signal(SIGALRM, read_timeout_handler);
  187. if(iRetVal < 0)
  188. printf("%s\r\n",strerror(errno));
  189. else
  190. {
  191. SendUDPMsg(&MessageOutPortList[ELEK_DEBUG_OUT],"elekIOaux : Connected to XPORT on MeteoBox");
  192. if(bEnableGUI)
  193. {
  194. wprintw(pStatusWin,"Connected to XPORT on MeteoBox\n");
  195. wrefresh(pStatusWin);
  196. }
  197. else
  198. printf("elekIOaux : Connected to XPORT on MeteoBox\r\n");
  199. }
  200. ;
  201. // read with timeout
  202. while(bGiveUp == false)
  203. {
  204. sigfunc = signal(SIGALRM, read_timeout_handler);
  205. alarm(2);
  206. // printf("entering read()\r\n");
  207. if( (iRetVal = read(sStructure->iFD,&cTheChar,1)) < 0)
  208. {
  209. if(errno == EINTR)
  210. printf("elekIOaux : socket timeout\r\n");
  211. else
  212. printf("read() error\r\n");
  213. }
  214. // we got data in time
  215. else
  216. {
  217. alarm(0);
  218. iTryCounts = 0;
  219. // printf("Got a Byte\r\n");
  220. // check for start of buffer
  221. if(cTheChar == '\n')
  222. {
  223. pTheBuffer = aTCPBuffer;
  224. iNumChars = 0;
  225. }
  226. else
  227. // check for end of buffer
  228. if((cTheChar == '\r') && (iNumChars > 0))
  229. {
  230. aTCPBuffer[iNumChars] = 0;
  231. MeteoBoxParseBuffer(aTCPBuffer,iNumChars,sStructure);
  232. pTheBuffer = aTCPBuffer;
  233. iNumChars = 0;
  234. }
  235. else
  236. // store char
  237. if(iNumChars < 1024)
  238. {
  239. (*pTheBuffer) = cTheChar;
  240. pTheBuffer++;
  241. iNumChars++;
  242. }
  243. else
  244. {
  245. printf("Buffer overflow\n\r");
  246. pTheBuffer = aTCPBuffer;
  247. iNumChars = 0;
  248. };
  249. };
  250. };
  251. printf("Trying to reconnect!\r\n");
  252. close(sStructure->iFD);
  253. };
  254. }
  255. void MeteoBoxParseBuffer(char* pBuffer, int iBuffLen, struct sMeteoBoxType* sDataStructure)
  256. {
  257. char* pRetVal;
  258. int iTokenNumber;
  259. char* pContext;
  260. //write(2,"Meteo: before lock\n\r",sizeof("Meteo: before lock\n\r"));
  261. pthread_mutex_lock(&mMeteoBoxMutex);
  262. //write(2,"Meteo: after lock\n\r",sizeof("Meteo: after lock\n\r"));
  263. pRetVal = strtok_r(pBuffer,";",&pContext);
  264. while(true)
  265. {
  266. if(pRetVal != NULL)
  267. {
  268. iTokenNumber++;
  269. // printf("Token %02d is '%s'\r\n",iTokenNumber,pRetVal);
  270. switch(iTokenNumber)
  271. {
  272. case 3:
  273. sDataStructure->dWindSpeed = strtod(pRetVal,NULL);
  274. case 9:
  275. sDataStructure->dAirTemp = strtod(pRetVal,NULL);
  276. case 12:
  277. sDataStructure->dRelHum = strtod(pRetVal,NULL);
  278. case 15:
  279. sDataStructure->uiWindDirection= atoi(pRetVal);
  280. case 18:
  281. sDataStructure->dGasSensorVoltage = strtod(pRetVal,NULL);
  282. default:
  283. break;
  284. };
  285. pRetVal=strtok_r(NULL,";",&pContext);
  286. }
  287. else
  288. break;
  289. };
  290. sDataStructure->Valid.Field.MeteoBoxDataValid = 1;
  291. //write(2,"Meteo: before unlock\n\r",sizeof("Meteo: before unlock\n\r"));
  292. pthread_mutex_unlock(&mMeteoBoxMutex);
  293. //write(2,"Meteo: after unlock\n\r",sizeof("Meteo: after unlock\n\r"));
  294. if(gPlotData)
  295. {
  296. printf("Wind Speed: %05.3f m/s\r\n",sDataStructure->dWindSpeed);
  297. printf("Air Temp: %05.3f °C\r\n",sDataStructure->dAirTemp);
  298. printf("Rel. Hum.: %05.3f %\r\n",sDataStructure->dRelHum);
  299. printf("Wind Dir.: %03d °\r\n" ,sDataStructure->uiWindDirection);
  300. printf("Gas Sensor: %05.3f V\r\n\r\n",sDataStructure->dGasSensorVoltage);
  301. }
  302. };