avls_communication.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. * Copyright (c) 2019 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include <sys/socket.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <sys/un.h>
  24. #include <netinet/in.h>
  25. #include <arpa/inet.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <poll.h>
  31. #include <time.h>
  32. #include "../common/common_defs.h"
  33. #include "../commhub/commhub.h"
  34. #include "../commhub/client_utils.h"
  35. //----------GLOBAL STATE VARIABLES
  36. time_t last_sync_attempt = 0; //Time of the last normal chirp in seconds since epoch
  37. time_t last_offline_chirp = 0; //Time of the last offline chirp in seconds since epoch
  38. int commhub_fd = -1; //File descriptor of our connection to the comm hub
  39. int server_fd = -1; //File descriptor of our connection to the sync server
  40. int avls_motion_interval = AVLS_MOTION_INTERVAL;
  41. int avls_still_interval = AVLS_STILL_INTERVAL;
  42. int load_avls_config()
  43. {
  44. int retval;
  45. FILE *f;
  46. char line[LINE_BUFFER_SIZE];
  47. int still = 0, motion = 0;
  48. f = fopen(AVLS_CONFIG_FILE, "rb");
  49. if(f)
  50. {
  51. while( !feof(f) && fgets(line, LINE_BUFFER_SIZE - 1, f) )
  52. {
  53. retval = sscanf(line, "%d %d", &motion, &still);
  54. if(retval == 2)
  55. {
  56. avls_motion_interval = motion;
  57. avls_still_interval = still;
  58. //DEBUG
  59. fprintf(stderr, "#avls (motion %i, still %i) interval\n", avls_motion_interval, avls_still_interval);
  60. //DEBUG
  61. fclose(f);
  62. return 0;
  63. }
  64. }
  65. fclose(f);
  66. }
  67. return -1;
  68. }
  69. //This function attempts to connect to the pass server...
  70. int connect_to_avls_server()
  71. {
  72. int fd;
  73. int retval;
  74. struct sockaddr_in addr;
  75. fd = socket(PF_INET, SOCK_STREAM, 0);
  76. if(fd < 0)
  77. return -1;
  78. addr.sin_family = AF_INET;
  79. addr.sin_port = htons(AVLS_SERVER_PORT);
  80. inet_aton(AVLS_SERVER_IP, &addr.sin_addr);
  81. retval = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
  82. if(retval < 0)
  83. {
  84. close(fd);
  85. return -2;
  86. }
  87. return fd;
  88. }
  89. int construct_avls_chirp(char *chirp, int size)
  90. {
  91. int len = 0;
  92. len += snprintf(chirp + len, size - len, "%d\t", get_equip_num());
  93. len += snprintf(chirp + len, size - len, "%d\t", driver_stat.logged_in_driver);
  94. len += snprintf(chirp + len, size - len, "%d\t", stop_stat.paddle);
  95. len += snprintf(chirp + len, size - len, "%d\t", stop_stat.route);
  96. len += snprintf(chirp + len, size - len, "%d\t", stop_stat.trip);
  97. len += snprintf(chirp + len, size - len, "%d\t", stop_stat.stop);
  98. len += snprintf(chirp + len, size - len, "%d\t", (int)time(NULL));
  99. len += snprintf(chirp + len, size - len, "%f\t", gps_stat.lat);
  100. len += snprintf(chirp + len, size - len, "%f\t", gps_stat.lon);
  101. len += snprintf(chirp + len, size - len, "%f\t", gps_stat.heading);
  102. len += snprintf(chirp + len, size - len, "%f\n", gps_stat.velocity);
  103. return len;
  104. }
  105. int send_avls_chirp(int fd)
  106. {
  107. char chirp[1024] = {0};
  108. int len = 0;
  109. len = construct_avls_chirp(chirp, sizeof(chirp));
  110. if(send(fd, chirp, len, 0) != len)
  111. {
  112. return -1;
  113. }
  114. return 0;
  115. }
  116. int send_offline_chirp()
  117. {
  118. char chirp[1024] = {0};
  119. int len = 0;
  120. struct message_record outgoing_msg;
  121. len = construct_avls_chirp(chirp, sizeof(chirp));
  122. if(len >= sizeof(chirp))
  123. {
  124. chirp[sizeof(chirp) - 1] = '\0';
  125. }
  126. else
  127. {
  128. chirp[len]='\0';
  129. }
  130. format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "OFFLINE AVLS: %s", chirp);
  131. if(commhub_fd >= 0)
  132. {
  133. return send_message(commhub_fd, &outgoing_msg);
  134. }
  135. return -1;
  136. }
  137. void maintain_ipc_hub_connect(char *progname)
  138. {
  139. struct message_record outgoing_msg;
  140. if(commhub_fd < 0) //if we have no connection to the communication hub
  141. {
  142. commhub_fd = connect_to_message_server(progname); //try and get one
  143. // printf("commhub_fd = %d\n", commhub_fd);
  144. if(commhub_fd >= 0) //if it worked
  145. {
  146. //Subscribe to the relevant status management mailboxes
  147. subscribe_to_default_messages(commhub_fd);
  148. //Request updated status information...
  149. prepare_message(&outgoing_msg, MAILBOX_STATUS_REQUEST, "", 0);
  150. send_message(commhub_fd,&outgoing_msg);
  151. }
  152. }
  153. }
  154. int main(int argc, char **argv)
  155. {
  156. struct pollfd fds[2];
  157. int nfds = 0;
  158. int poll_return = 0;
  159. int read_return = 0;
  160. int i;
  161. struct message_record incoming_msg;
  162. //------------------
  163. load_avls_config();
  164. configure_signal_handlers(argv[0]);
  165. maintain_ipc_hub_connect(argv[0]);
  166. //Register our default keep-up-with-system status callbacks
  167. register_system_status_callbacks();
  168. while( exit_request_status == EXIT_REQUEST_NONE )
  169. {
  170. time_t now = time(NULL);
  171. int sync_threshold = 0;
  172. RESET_WATCHDOG();
  173. if(hup_request_status)
  174. {
  175. load_avls_config();
  176. hup_request_status = 0;
  177. }
  178. maintain_ipc_hub_connect(argv[0]);
  179. if(server_fd < 0) //If we don't have a connection to the sync server...
  180. {
  181. if( (now - last_sync_attempt) > DEFAULT_CONNECT_RETRY ) //See if it is time to try again
  182. {
  183. if( tunnel_is_up() ) //and if the tunnel thinks it is up
  184. {
  185. server_fd = connect_to_avls_server(); //if so, try again...
  186. // printf("server_fd = %d\n", server_fd);
  187. if(server_fd >= 0) //if it worked
  188. {
  189. last_sync_attempt = 0;
  190. }
  191. else
  192. {
  193. last_sync_attempt = now;
  194. }
  195. }
  196. }
  197. }
  198. nfds=0;
  199. //-----------------------------------------------
  200. //
  201. // Figure out what our time threshold is to transmit
  202. // a message based on whether we're moving or still.
  203. //
  204. //-----------------------------------------------
  205. if(gps_stat.velocity > MOTION_THRESHOLD) //See if the bus is in motion...
  206. {
  207. sync_threshold = avls_motion_interval; //if so, we want to send AVLS chirps at higher rate
  208. }
  209. else
  210. {
  211. sync_threshold = avls_still_interval; //if not, we send them at a lower default rate
  212. }
  213. if(server_fd >= 0) //---------- If we have an active connection to the AVLS server through the tunnel
  214. {
  215. fds[nfds].fd = server_fd; //Add it to the list of things we must poll()
  216. fds[nfds].events = 0;
  217. // See if we have gone long enough to need to transmit a message AND have valid GPS data to transmit
  218. if( ((now - last_sync_attempt) > sync_threshold) && gps_stat.gps_good )
  219. {
  220. fds[nfds].events |= POLLOUT; //If so, ask poll to see if we have buffer space to transmit one
  221. }
  222. nfds++; //either way, add this FD to the poll() list.
  223. }
  224. else //---------- Otherwise, if we have no connection to the AVLS server
  225. {
  226. // See if it is time to transmit an offline chirp AND we have valid GPS data to transmit
  227. if( ((now - last_offline_chirp) > sync_threshold) && gps_stat.gps_good )
  228. {
  229. if(send_offline_chirp() == 0) //If so, stick one in the diagnostic log at DEBUG priority
  230. {
  231. last_offline_chirp = now; //Remember that we've done so if it worked.
  232. }
  233. }
  234. }
  235. if(commhub_fd >= 0)
  236. {
  237. fds[nfds].fd = commhub_fd;
  238. fds[nfds].events = POLLIN;
  239. nfds++;
  240. }
  241. if(nfds > 0)
  242. {
  243. poll_return = poll(fds, nfds, POLL_TIMEOUT);
  244. }
  245. else
  246. {
  247. usleep(POLL_TIMEOUT * 1000);
  248. poll_return = 0;
  249. }
  250. // printf("Poll returns %d (of %d)\n", poll_return, nfds);
  251. // for(i=0; i < nfds; i++)
  252. // {
  253. // printf("\t%d: fd=%d ev=%d rev=%d\n", i, fds[i].fd, fds[i].events, fds[i].revents);
  254. // }
  255. if(poll_return <= 0)
  256. {
  257. continue;
  258. }
  259. for(i=0; i < nfds; i++)
  260. {
  261. // printf("Processing Poll Result %d\n",i);
  262. if( fds[i].fd == server_fd )
  263. {
  264. //If we've lost connection, break this loop and poll all over again
  265. if(fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
  266. {
  267. close(server_fd);
  268. server_fd = -1;
  269. break;
  270. }
  271. if(fds[i].revents & POLLOUT)
  272. {
  273. //sent a query here...
  274. // printf("Trying to write to server...\n");
  275. read_return = send_avls_chirp(server_fd);
  276. //and then update our last sync attempt time
  277. last_sync_attempt = now;
  278. if(read_return < 0)
  279. {
  280. close(server_fd);
  281. server_fd = -1;
  282. break;
  283. }
  284. }
  285. }
  286. else if( fds[i].fd == commhub_fd )
  287. {
  288. //If we've lost connection, break this loop and poll all over again
  289. if(fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
  290. {
  291. close(commhub_fd);
  292. commhub_fd = -1;
  293. break;
  294. }
  295. if(fds[i].revents & POLLIN)
  296. {
  297. // printf("Trying to read from hub...\n");
  298. read_return = get_message(commhub_fd, &incoming_msg);
  299. if( read_return < 0 )
  300. {
  301. close(commhub_fd);
  302. commhub_fd = -1;
  303. break;
  304. }
  305. process_message(&incoming_msg); //This passes the received message through the callback list
  306. }
  307. }
  308. }
  309. }
  310. return 0;
  311. }