Shared Wifi resources and Network connection. Complex Question about using Semaphore
Posted: Thu Jun 20, 2024 4:02 pm
<r>I would like the following help:<br/>
<br/>
I have a complex hardware that works with ESP32 S3 16MB of Ram and ESP IDF 5<br/>
<br/>
The function of this hardware is to connect to Wifi and ping different IP devices.<br/>
<br/>
This ping command is not done multiple times. I mean that I don’t call the ping function several times. I wait for one ping to finish and start another.<br/>
<br/>
I did it this way, because I understand that it was safer.<br/>
<br/>
However, on this same hardware I have two MQTT connections, one connection sends information every 1 minute and another connection listens to a topic that can receive data every moment.<br/>
<br/>
My question is is this connection to the wifi hardware a system restriction? Do I have to apply a Semaphoro or event group to each thing?<br/>
<br/>
Currently MQTT and Ping run at the same time. But I don’t know if it’s correct.<br/>
<br/>
What do you think ?<br/>
<br/>
I’m going to paste a part of the code here so you can understand a little of the context and also a photo of the product.<br/>
<CODEBOX codebox="c" file="Untitled.c"><s></e></CODEBOX>
<br/>
and<br/>
<br/>
The ping code:<br/>
<CODEBOX codebox="c" file="Untitled.c"><s></e></CODEBOX>
The MQTT Code:<br/>
<CODEBOX codebox="c" file="Untitled.c"><s></e></CODEBOX>
My Setup Screen:</r>
<br/>
I have a complex hardware that works with ESP32 S3 16MB of Ram and ESP IDF 5<br/>
<br/>
The function of this hardware is to connect to Wifi and ping different IP devices.<br/>
<br/>
This ping command is not done multiple times. I mean that I don’t call the ping function several times. I wait for one ping to finish and start another.<br/>
<br/>
I did it this way, because I understand that it was safer.<br/>
<br/>
However, on this same hardware I have two MQTT connections, one connection sends information every 1 minute and another connection listens to a topic that can receive data every moment.<br/>
<br/>
My question is is this connection to the wifi hardware a system restriction? Do I have to apply a Semaphoro or event group to each thing?<br/>
<br/>
Currently MQTT and Ping run at the same time. But I don’t know if it’s correct.<br/>
<br/>
What do you think ?<br/>
<br/>
I’m going to paste a part of the code here so you can understand a little of the context and also a photo of the product.<br/>
<CODEBOX codebox="c" file="Untitled.c"><s>
- </s>void v_Pingador(void *parameters) {<br/>
- while(1){<br/>
- for (int i = 0; i < MAX_IP_COUNT; i++) {<br/>
- if (Device[i].Servico != NULL && strcmp(Device[i].Servico, "ping") == 0) {<br/>
- if(f_Ipv4Valid(Device[i].ip_addresses)){<br/>
- xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, portMAX_DELAY);<br/>
- xSemaphoreTake(SemaphorePing, portMAX_DELAY);<br/>
- f_Ping((void *)&Device[i]);<br/>
- }<br/>
- }<br/>
- }<br/>
- }<br/>
- }<br/>
- <br/>
- void f_CoreSubscribe(){<br/>
- for (int i = 0; i < MAX_IP_COUNT; i++) {<br/>
- if (Device[i].Servico != NULL && strcmp(Device[i].Servico, "mqtt") == 0) {<br/>
- if(Device[i].topico != NULL){<br/>
- if(f_ValidaTopico(Device[i].topico)){<br/>
- f_subscribe(Device[i].topico);<br/>
- }<br/>
- }<br/>
- }<br/>
- }<br/>
- }<br/>
- <br/>
- void v_Display_0(void *pvParameters) {<br/>
- int8_t Alarme_Device;<br/>
- int32_t TimeOut_Count[MAX_IP_COUNT];<br/>
- unsigned long received_item;<br/>
- char ms_str[22];<br/>
- char ms_str2[26];<br/>
- while(1) {<br/>
- char * receivedMqtt;<br/>
- for (int i=0; i<MAX_IP_COUNT;i++){<br/>
- xEventGroupWaitBits(EventG_Display, BIT_0, pdFALSE, pdFALSE, portMAX_DELAY);<br/>
- if (Device[i].xQueue!=NULL){<br/>
- if (Device[i].Servico != NULL && strcmp(Device[i].Servico, "ping") == 0){<br/>
- if (xQueueReceive(Device[i].xQueue, &received_item, 0)) {<br/>
- if (received_item != UINT32_MAX){<br/>
- snprintf(ms_str, sizeof(ms_str), "Tempo - %ldms", received_item);<br/>
- f_Mostra(ms_str, Device[i].ip_addresses, Device[i].Device_Name, Clear_OFF, i);<br/>
- TimeOut_Count[i] = 0;<br/>
- }else{<br/>
- snprintf(ms_str2, sizeof(ms_str2), "%s - Outs:%lu", Device[i].Device_Name, TimeOut_Count[i]+1);<br/>
- f_Mostra("TIME OUT!!", Device[i].ip_addresses, ms_str2, Clear_ON, i);<br/>
- TimeOut_Count[i]++;<br/>
- }<br/>
- EventBits_t bits = xEventGroupGetBits(EventG_Alarme);<br/>
- if(TimeOut_Count[i]>Alarme_NumAtivarStatus && !(bits & BIT_0)){<br/>
- xEventGroupSetBits(EventG_Alarme, BIT_0);<br/>
- f_Led(LED_VERDE, Led_Desliga);<br/>
- urlFinal = f_urlFinal(AlarmeWebHookURL_val, AlarmeWebHookText_val, Device[i].Device_Name, Device[i].ip_addresses);<br/>
- Alarme_Device = i;<br/>
- AlarmeSonoroSuprimir = true;<br/>
- }else if(i == Alarme_Device && TimeOut_Count[i] == 0 && (bits & BIT_0)){<br/>
- xEventGroupClearBits(EventG_Alarme, BIT_0);<br/>
- AlarmeSonoroSuprimir = false;<br/>
- f_Led(LED_VERDE, Led_Liga);<br/>
- ESP_LOGW(TAG, "Led Verde...ligado");<br/>
- }<br/>
- }<br/>
- } else if (Device[i].Servico != NULL && strcmp(Device[i].Servico, "mqtt") == 0){<br/>
- if (xQueueReceive(Device[i].xQueue, &receivedMqtt, 0)) {<br/>
- f_Mostra(receivedMqtt, Device[i].topico,Device[i].Device_Name, Clear_OFF, i);<br/>
- }<br/>
- <br/>
- }<br/>
- }<br/>
- else{<br/>
- if (Texto_Display_Vazio != NULL && (strlen(Texto_Display_Vazio)>3)) {<br/>
- f_Mostra("", "", Texto_Display_Vazio, Clear_OFF, i);<br/>
- }<br/>
- }<br/>
- //ESP_LOGW(TAG, "Device[%i]", i);<br/>
- }<br/>
- vPortYield();<br/>
- }<br/>
- }<e>
<br/>
and<br/>
<br/>
The ping code:<br/>
<CODEBOX codebox="c" file="Untitled.c"><s>
- </s>void on_ping_success(esp_ping_handle_t hdl, void *args) {<br/>
- uint32_t elapsed_time_ms;<br/>
- esp_err_t ret;<br/>
- ip_addr_t target_addr;<br/>
- device_t *Device_X = (device_t *)args;<br/>
- ret = esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time_ms, sizeof(uint32_t));<br/>
- if (ret != ESP_OK) {ESP_LOGE("TAG", "Erro ao obter o tempo decorrido: %d", ret);return;}<br/>
- ret = esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(ip_addr_t));<br/>
- if (ret != ESP_OK) {ESP_LOGE("TAG", "Erro ao obter o endereço IP alvo: %d", ret);return;}<br/>
- xQueueSend(Device_X->xQueue, &elapsed_time_ms, 100);<br/>
- }<br/>
- <br/>
- void on_ping_timeout(esp_ping_handle_t hdl, void *args) {<br/>
- esp_err_t ret;<br/>
- ip_addr_t target_addr;<br/>
- device_t *Device_X = (device_t *)args;<br/>
- ret = esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(ip_addr_t));<br/>
- if (ret != ESP_OK) {ESP_LOGE("TAG", "Erro ao obter o endereço IP alvo: %d", ret);return;}<br/>
- uint32_t Max = UINT32_MAX;<br/>
- xQueueSend(Device_X->xQueue, &Max, 100);<br/>
- }<br/>
- <br/>
- void on_ping_end(esp_ping_handle_t hdl, void *args) {<br/>
- esp_err_t ret;<br/>
- ret = esp_ping_delete_session(hdl);<br/>
- if (ret != ESP_OK) {printf("Erro ao encerrar a sessão de ping: %d\n", ret);return;}<br/>
- ip_addr_t target_addr;<br/>
- ret = esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(ip_addr_t));<br/>
- xSemaphoreGive(SemaphorePing);<br/>
- }<br/>
- <br/>
- void f_Ping(void *parameters) {<br/>
- device_t *Device_X = (device_t *)parameters;<br/>
- if (f_PingValida(Device_X)==false) {xSemaphoreGive(SemaphorePing);return;}<br/>
- ip_addr_t ip;<br/>
- ip.u_addr.ip4.addr = esp_ip4addr_aton(Device_X->ip_addresses);<br/>
- ip.type = IPADDR_TYPE_V4;<br/>
- esp_ping_config_t ping_config = {<br/>
- .target_addr = ip, // Endereço IP do host a ser pingado<br/>
- .count = Device_X->count, // Número de pacotes a serem enviados<br/>
- .interval_ms = Device_X->interval_ms, // Intervalo entre os envios de pacotes (em milissegundos)<br/>
- .data_size = Device_X->data_size, // Tamanho dos dados do pacote ICMP<br/>
- .timeout_ms = Device_X->timeout_ms, // Tempo limite para esperar por uma resposta (em milissegundos)<br/>
- .tos = Device_X->tos, // Tipo de Serviço (TOS) para o pacote IP<br/>
- .ttl = Device_X->ttl, // Tempo de Vida (TTL) do pacote IP<br/>
- //.interface = NULL, // Interface de rede a ser usada para o ping (NULL para usar a interface padrão)<br/>
- .task_stack_size = 3000,<br/>
- .task_prio = 5<br/>
- };<br/>
- esp_ping_callbacks_t ping_callbacks = {.on_ping_success = on_ping_success,.on_ping_timeout = on_ping_timeout,.on_ping_end = on_ping_end,.cb_args = (void *)Device_X};<br/>
- esp_ping_handle_t ping_handle;<br/>
- esp_err_t ret = esp_ping_new_session(&ping_config, &ping_callbacks, &ping_handle);<br/>
- if (ret != ESP_OK) {printf("Erro ao criar a sessão de ping: %d\n", ret);ESP_LOGE(TAG, "IP[%s]", Device_X->ip_addresses);xSemaphoreGive(SemaphorePing);return;}<br/>
- ret = esp_ping_start(ping_handle);<br/>
- if (ret != ESP_OK) {printf("Erro ao iniciar o ping: %d\n", ret);ESP_LOGW(TAG, "IP[%s]", Device_X->ip_addresses);xSemaphoreGive(SemaphorePing);return;}<br/>
- }<e>
The MQTT Code:<br/>
<CODEBOX codebox="c" file="Untitled.c"><s>
- </s>
- //-----------------------------------------------------------------------------------------------------------------------<br/>
- //---MQTT 1--------------------------------------------------------------------------------------------------------------<br/>
- //-----------------------------------------------------------------------------------------------------------------------<br/>
- static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data){<br/>
- ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);<br/>
- esp_mqtt_event_handle_t event = event_data;<br/>
- esp_mqtt_client_handle_t client = event->client;<br/>
- switch ((esp_mqtt_event_id_t)event_id) {<br/>
- case MQTT_EVENT_CONNECTED:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");<br/>
- f_CoreSubscribe();<br/>
- break;<br/>
- case MQTT_EVENT_DISCONNECTED:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");<br/>
- break;<br/>
- case MQTT_EVENT_DATA:<br/>
- char *topic = strndup(event->topic, event->topic_len);<br/>
- char *data = strndup(event->data, event->data_len);<br/>
- if (topic && data) {f_SendDataMqtt(topic, data);} else {ESP_LOGE(TAG, "Falha ao alocar memória para tópico ou payload");}<br/>
- free(topic);free(data);<br/>
- break;<br/>
- case MQTT_EVENT_ERROR:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_ERROR");<br/>
- if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {<br/>
- log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);<br/>
- log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);<br/>
- log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);<br/>
- ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));<br/>
- }<br/>
- break;<br/>
- default:<br/>
- ESP_LOGI(TAG, "Other event id:%d", event->event_id);<br/>
- break;<br/>
- }<br/>
- }<br/>
- //-----------------------------------------------------------------------------------------------------------------------<br/>
- //---MQTT 2--------------------------------------------------------------------------------------------------------------<br/>
- //-----------------------------------------------------------------------------------------------------------------------<br/>
- static void mqtt_event_handler_out(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data){<br/>
- ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);<br/>
- esp_mqtt_event_handle_t event = event_data;<br/>
- esp_mqtt_client_handle_t client = event->client;<br/>
- switch ((esp_mqtt_event_id_t)event_id) {<br/>
- case MQTT_EVENT_CONNECTED:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");<br/>
- esp_mqtt_client_subscribe(client, TOPICO_OTA, 0);<br/>
- esp_mqtt_client_subscribe(client, TOPICO_URL, 0);<br/>
- esp_mqtt_client_subscribe(client, f_topico(TOPICO_LICENCA), 0);<br/>
- f_mqttPublica(f_topico(zMQTT_sufixo), f_prepJsonConfig(mqtt_ON), cMqttOut);<br/>
- f_mqttPublica(f_topico(zMQTT_sufixo_Config), f_prepJsonConfig(mqtt_Config), cMqttOut);<br/>
- break;<br/>
- case MQTT_EVENT_DISCONNECTED:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");<br/>
- break;<br/>
- case MQTT_EVENT_DATA:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_DATA");<br/>
- printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);<br/>
- printf("DATA=%.*s\r\n", event->data_len, event->data);<br/>
- //Testa qual tópico foi recebido e começa a fazer as coisas conforme o tópico<br/>
- if (strncmp(event->topic, TOPICO_OTA, event->topic_len) == 0) {<br/>
- f_otaMQTT(event->topic, event->topic_len, event->data, event->data_len);<br/>
- }<br/>
- if (strncmp(event->topic, TOPICO_URL, event->topic_len) == 0) {<br/>
- ESP_LOGW(TAG, "TOPICO URL");//Desenvolver ainda...<br/>
- }<br/>
- if (strncmp(event->topic, f_topico(TOPICO_LICENCA), event->topic_len) == 0) {<br/>
- cJSON *token = cJSON_GetObjectItem(cJSON_Parse((char *)event->data), "token");<br/>
- if (!cJSON_IsString(token)){ESP_LOGE(TAG, "Erro na leitura do json");}<br/>
- f_nvsSet(zTokenTemp, token->valuestring, false);<br/>
- xTaskCreatePinnedToCore(v_InsertLicenca, "v_InsertLicenca", 8000, NULL, tskIDLE_PRIORITY, NULL, tskNO_AFFINITY);<br/>
- }<br/>
- break;<br/>
- case MQTT_EVENT_ERROR:<br/>
- ESP_LOGI(TAG, "MQTT_EVENT_ERROR");<br/>
- if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {<br/>
- log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);<br/>
- log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);<br/>
- log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);<br/>
- ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));<br/>
- }<br/>
- break;<br/>
- default:<br/>
- ESP_LOGI(TAG, "Other event id:%d", event->event_id);<br/>
- break;<br/>
- }<br/>
- }<br/>
- <br/>
- <br/>
- void f_mqttPublica(const char * topico, const char * payload, esp_mqtt_client_handle_t handle){<br/>
- EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, 200);<br/>
- if((bits & WIFI_BIT_0)){<br/>
- int len = strlen(payload);<br/>
- //xSemaphoreTake(SemaphorePing, portMAX_DELAY);<br/>
- int resp = esp_mqtt_client_publish(handle, topico,payload,len,0,0);<br/>
- if (resp==0){<br/>
- ESP_LOGI(TAG, "JSON publicado via MQTT. Com sucesso");<br/>
- }else if(resp<0){<br/>
- ESP_LOGE(TAG, "JSON publicado via MQTT. Erro na publicação");<br/>
- }<br/>
- //xSemaphoreGive(SemaphorePing);<br/>
- }<br/>
- }<br/>
- <br/>
- extern const uint8_t ca_cert_pem_start[] asm("_binary_ca_cert_pem_start");<br/>
- extern const uint8_t ca_cert_pem_end[] asm("_binary_ca_cert_pem_end");<br/>
- <br/>
- void f_setupMQTT(void){<br/>
- Dados_Mqtt_t DadosMqtt, DadosMqttout;<br/>
- if(f_DadosMqtt(&DadosMqtt) == ESP_OK){<br/>
- ESP_LOGW(TAG, "MQTT");<br/>
- //ESP_LOGW(TAG, "cert:%s", DadosMqtt.mqtt_cert);<br/>
- //ESP_LOGW(TAG, "cert:%i", DadosMqtt.mqtt_cert_len);<br/>
- esp_mqtt_client_config_t mqtt_cfg = {<br/>
- .broker.address.uri = DadosMqtt.mqtt_server,<br/>
- .broker.address.port = DadosMqtt.mqtt_port,<br/>
- .broker.verification.certificate = (const char *)ca_cert_pem_start,<br/>
- .broker.verification.certificate_len = (ca_cert_pem_end - ca_cert_pem_start),<br/>
- //.broker.verification.certificate = DadosMqtt.mqtt_cert,<br/>
- //.broker.verification.certificate_len = DadosMqtt.mqtt_cert_len,<br/>
- .credentials.username = DadosMqtt.mqtt_user,<br/>
- .credentials.authentication.password = DadosMqtt.mqtt_pass,<br/>
- .credentials.client_id = "enervision",<br/>
- .session.last_will.msg = f_prepJsonConfig(mqtt_OFF),<br/>
- .session.last_will.msg_len = strlen(f_prepJsonConfig(mqtt_OFF)),<br/>
- .session.last_will.topic = f_topico(zMQTT_sufixo),<br/>
- .session.last_will.retain = true,<br/>
- .session.last_will.qos = 1,<br/>
- .session.keepalive = 2 <br/>
- };<br/>
- <br/>
- //Fazer isso no futuro - v.2.0 //Não conectou ... Busca o backup por OTA ?<br/>
- //Antes de buscar a conexão via backup, conferir conexões, ping, verificar se o dns <br/>
- EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, pdMS_TO_TICKS(40000));<br/>
- if((bits & WIFI_BIT_0)){<br/>
- client = esp_mqtt_client_init(&mqtt_cfg);<br/>
- esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);<br/>
- esp_mqtt_client_start(client);<br/>
- }<br/>
- }<br/>
- <br/>
- if(f_DadosMqttout(&DadosMqttout) == ESP_OK){<br/>
- ESP_LOGW(TAG, "MQTT OUT");<br/>
- esp_mqtt_client_config_t mqtt_cfg_out = {<br/>
- .broker.address.uri = DadosMqttout.mqtt_server,<br/>
- .broker.address.port = DadosMqttout.mqtt_port,<br/>
- .broker.verification.certificate = (const char *)ca_cert_pem_start,<br/>
- .broker.verification.certificate_len = (ca_cert_pem_end - ca_cert_pem_start),<br/>
- .credentials.username = DadosMqttout.mqtt_user,<br/>
- .credentials.authentication.password = DadosMqttout.mqtt_pass,<br/>
- .credentials.client_id = f_serialNumber(),<br/>
- .session.last_will.msg = f_prepJsonConfig(mqtt_OFF),<br/>
- .session.last_will.msg_len = strlen(f_prepJsonConfig(mqtt_OFF)),<br/>
- .session.last_will.topic = f_topico(zMQTT_sufixo),<br/>
- .session.last_will.retain = true,<br/>
- .session.last_will.qos = 1,<br/>
- .session.keepalive = 2 <br/>
- };<br/>
- EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, pdMS_TO_TICKS(40000));<br/>
- if((bits & WIFI_BIT_0)){<br/>
- cMqttOut = esp_mqtt_client_init(&mqtt_cfg_out);<br/>
- esp_mqtt_client_register_event(cMqttOut, ESP_EVENT_ANY_ID, mqtt_event_handler_out, NULL);<br/>
- esp_mqtt_client_start(cMqttOut);<br/>
- }<br/>
- }<br/>
- }
- <e>
My Setup Screen:</r>