udp_client.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <string.h>
  2. #include <sys/param.h>
  3. #include "sdkconfig.h"
  4. #include "freertos/FreeRTOS.h"
  5. #include "freertos/task.h"
  6. #include "freertos/event_groups.h"
  7. #include "esp_system.h"
  8. #include "esp_wifi.h"
  9. #include "esp_event.h"
  10. #include "esp_log.h"
  11. #include "nvs_flash.h"
  12. #include "esp_netif.h"
  13. #include "lwip/err.h"
  14. #include "lwip/sockets.h"
  15. #include "lwip/sys.h"
  16. #include <lwip/netdb.h>
  17. #include "udp_client.h"
  18. #include "wifi.h"
  19. #include "nexaTransmit.h"
  20. /**********************************************************************************
  21. * For sending and receiving UDP-Data from the Debian-server use these commands:
  22. * echo "<NT4C90AD91>" | nc -uv 192.168.1.164 53000
  23. * nc -lu -p 53000
  24. **********************************************************************************/
  25. #ifdef WIFI_ENABLED
  26. static QueueHandle_t udpTxQueue = NULL; // Queue for transmitting UDP-Data to back-end server
  27. static QueueHandle_t udpForwardQueue = NULL; // Queue for forwarding NEXA-UDP-Data to next transceiver
  28. static int socket_fd;
  29. static struct sockaddr_in backEndAddress; // Address to back-end server
  30. static struct sockaddr_in backEndAddressSensorData; // Address to back-end server (sensor)
  31. static struct sockaddr_in forwardAddress; // Address to next transceiver for NEXA-code-forwarding
  32. static void setupConnection() {
  33. struct sockaddr_in recvFromAddress;
  34. closesocket(socket_fd);
  35. // This Address is used for sending to the back-end server
  36. backEndAddress.sin_addr.s_addr = inet_addr(CONFIG_BACK_END_SERVER_IP_ADDRESS);
  37. backEndAddress.sin_family = AF_INET;
  38. backEndAddress.sin_port = htons(CONFIG_UDP_PORT_NO);
  39. // This Address is used for sending to the back-end server for sensor-data (different port)
  40. backEndAddressSensorData.sin_addr.s_addr = inet_addr(CONFIG_BACK_END_SERVER_IP_ADDRESS);
  41. backEndAddressSensorData.sin_family = AF_INET;
  42. backEndAddressSensorData.sin_port = htons(CONFIG_UDP_PORT_NO_FOR_SENSOR_DATA);
  43. // This Address is used for forwaring NEXA codes to next transceiver
  44. forwardAddress.sin_addr.s_addr = inet_addr(CONFIG_NEXT_FORWARD_IP_ADDRESS);
  45. forwardAddress.sin_family = AF_INET;
  46. forwardAddress.sin_port = htons(CONFIG_UDP_PORT_NO);
  47. // Wait for WiFi to be connected first
  48. while( commIsUpAndRunning == 0 ) vTaskDelay(500 / portTICK_PERIOD_MS);
  49. socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  50. if (socket_fd < 0) ESP_LOGE("UDP","Socket error");
  51. // Bind our server socket to a port.
  52. // We listen on this port from ANY other host. It could be the
  53. // back-end server, or it could be another Transceiver that forwards
  54. recvFromAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  55. recvFromAddress.sin_family = AF_INET;
  56. recvFromAddress.sin_port = htons(CONFIG_UDP_PORT_NO);
  57. if( (bind(socket_fd, (const struct sockaddr *)&recvFromAddress, sizeof(struct sockaddr_in))) == -1 )
  58. ESP_LOGE("UDP","Bind error");
  59. else
  60. ESP_LOGI("UDP","UDP Rx Bind.");
  61. }
  62. void udp_client_task(void *pvParameter)
  63. {
  64. int recv_len;
  65. char dataBuff[UDP_QUEUE_OBJ_LENGTH];
  66. setupConnection();
  67. while(1)
  68. {
  69. memset(dataBuff,0,UDP_QUEUE_OBJ_LENGTH);
  70. // Receive
  71. if( (recv_len = recvfrom(socket_fd, dataBuff, UDP_QUEUE_OBJ_LENGTH,MSG_DONTWAIT, NULL, NULL)) > 0 ) {
  72. if( dataBuff[recv_len-1] == '\n' ) dataBuff[recv_len-1] = '\0';
  73. sendNexaCodeStr(dataBuff);
  74. ESP_LOGI("UDP","UDP Task: Data: %s -- %d" , dataBuff, recv_len);
  75. }
  76. else if( recv_len == -1 && errno != 11 ) {
  77. ESP_LOGE("UDP", "Error occurred during recvfrom: errno %d", errno);
  78. }
  79. // Transmit
  80. while( xQueueReceive( udpTxQueue, &dataBuff, 0 ) == pdTRUE ) {
  81. // Last byte contains type of data
  82. const uint8_t dataType = dataBuff[UDP_QUEUE_OBJ_LENGTH-1];
  83. ESP_LOGI("UDP","Send data:%s Type:%u",dataBuff,dataType);
  84. if( dataType == 0 ) {
  85. sendto(socket_fd, dataBuff, strlen(dataBuff), 0, (struct sockaddr *)&backEndAddress, sizeof(backEndAddress));
  86. }
  87. else if( dataType == 1 ) {
  88. sendto(socket_fd, dataBuff, strlen(dataBuff), 0, (struct sockaddr *)&backEndAddressSensorData, sizeof(backEndAddressSensorData));
  89. }
  90. else {
  91. ESP_LOGE("UDP","Wrong dataType:%u",dataType);
  92. }
  93. }
  94. // Forward NEXT Codes to next transceiver
  95. while( xQueueReceive( udpForwardQueue, &dataBuff, 0 ) == pdTRUE ) {
  96. ESP_LOGI("UDP","Forward NEXA-data:%s",dataBuff);
  97. sendto(socket_fd, dataBuff, strlen(dataBuff), 0, (struct sockaddr *)&forwardAddress, sizeof(forwardAddress));
  98. }
  99. vTaskDelay(50 / portTICK_RATE_MS);
  100. }
  101. vTaskDelete(NULL);
  102. }
  103. // Public interface for sending a UDP Message to the back-end server.
  104. // Argument #1 must be UDP_QUEUE_OBJ_LENGTH chars in length.
  105. // In the last data byte transfered, the type of data is specified
  106. void sendUDPMessage(char *p, bool sensorData) {
  107. char data[UDP_QUEUE_OBJ_LENGTH];
  108. data[0] = '<';
  109. data[1] = CONFIG_UNIT_ID + 'A'; // Source
  110. data[2] = 'A'; // Destination
  111. if( p[0] == '<') {
  112. strncpy(data+3, p+1, UDP_QUEUE_OBJ_LENGTH-4);
  113. if( strchr(data,'>') != NULL ) {
  114. if( sensorData == true )
  115. data[UDP_QUEUE_OBJ_LENGTH-1] = 1; // Sensor data
  116. else
  117. data[UDP_QUEUE_OBJ_LENGTH-1] = 0; // NEXA
  118. if( udpTxQueue != NULL ) xQueueSend( udpTxQueue, data, 0 );
  119. }
  120. }
  121. }
  122. // Public interface for forwaring a NEXA code to the next transceiver.
  123. void forwardNEXAMessage(char *p) {
  124. if( udpForwardQueue != NULL ) xQueueSend( udpForwardQueue, p, 0 );
  125. }
  126. void udpClientInit()
  127. {
  128. ESP_ERROR_CHECK(esp_netif_init());
  129. ESP_ERROR_CHECK(esp_event_loop_create_default());
  130. udpTxQueue = xQueueCreate( 5, UDP_QUEUE_OBJ_LENGTH );
  131. udpForwardQueue = xQueueCreate( 5, UDP_QUEUE_OBJ_LENGTH );
  132. xTaskCreate(udp_client_task, "udp_client", 4096, NULL, 5, NULL);
  133. }
  134. #endif