Sat, 01 Apr 2023 21:06:59 +0200
Added task_out to drive the relays and led lights. Added NVS namespace to store the state of the outputs. Respond to subscribed MQTT topics to set new output values.
4 | 1 | /** |
2 | * @file task_wifi.c | |
3 | * @brief WiFi task. Connects to a known Access Point. | |
4 | */ | |
5 | ||
6 | ||
7 | #include "config.h" | |
8 | ||
9 | ||
10 | static const char *TAG = "task_wifi"; | |
11 | ||
12 | #define ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID | |
13 | #define ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD | |
14 | ||
15 | SemaphoreHandle_t xSemaphoreWiFi = NULL; ///< Semaphore WiFi task. | |
16 | EventGroupHandle_t xEventGroupWifi; ///< Events WiFi task. | |
17 | wifi_config_t wifi_Config = { ///< Current STA configuration. | |
18 | .sta = { | |
19 | .ssid = ESP_WIFI_SSID, | |
20 | .password = ESP_WIFI_PASS, | |
21 | .scan_method = WIFI_FAST_SCAN, | |
22 | .sort_method = WIFI_CONNECT_AP_BY_SECURITY, | |
23 | .threshold.rssi = -127, | |
24 | .threshold.authmode = WIFI_AUTH_WPA2_PSK, | |
25 | }, | |
26 | }; | |
27 | WIFI_State *wifi_state = NULL; ///< Public state for other tasks. | |
28 | esp_netif_t *sta_netif = NULL; ///< Station interface | |
29 | ||
30 | ||
31 | const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT1; ///< When set, means a client requested to disconnect from currently connected AP. | |
32 | const int TASK_WIFI_REQUEST_STA_CONNECT = BIT2; ///< When set, means a client requested to connect to an access point. | |
33 | ||
34 | const int TASK_WIFI_HAS_IP = BIT3; ///< Indicate that we have an IP address | |
35 | const int TASK_WIFI_STA_FAILED = BIT5; ///< Indicate that we could not get a connection to AP as station. | |
36 | const int TASK_WIFI_STA_DISCONNECTED = BIT6; ///< Indicate that we are disconnected from an ap station. | |
37 | const int TASK_WIFI_STA_CONNECTED = BIT7; ///< Indicate that we are connected to AP as station, flip of BIT6. | |
38 | ||
39 | ||
40 | /****************************************************************************/ | |
41 | ||
42 | ||
43 | bool ready_WiFi(void) | |
44 | { | |
45 | if (wifi_state->STA_connected && wifi_state->STA_online) | |
46 | return true; | |
47 | return false; | |
48 | } | |
49 | ||
50 | ||
51 | ||
52 | void request_WiFi(bool connect) | |
53 | { | |
54 | if (connect) | |
55 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); | |
56 | else | |
57 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); | |
58 | } | |
59 | ||
60 | ||
61 | ||
62 | static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) | |
63 | { | |
64 | switch (event_id) { | |
65 | ||
66 | case WIFI_EVENT_STA_START: | |
67 | ESP_LOGI(TAG, "Event wifi START"); | |
68 | // Set the hostname for the dhcp client. | |
69 | #ifdef CONFIG_CODE_PRODUCTION | |
70 | ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "balkon")); | |
71 | #endif | |
72 | #ifdef CONFIG_CODE_TESTING | |
73 | ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "wemos")); | |
74 | #endif | |
75 | // ESP_ERROR_CHECK(esp_wifi_connect()); | |
76 | break; | |
77 | ||
78 | case WIFI_EVENT_STA_CONNECTED: { | |
79 | // system_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data; | |
80 | wifi_ap_record_t ap_info; | |
81 | esp_wifi_sta_get_ap_info(&ap_info); | |
82 | ESP_LOGI(TAG, "Event STA connected rssi=%d", ap_info.rssi); | |
83 | if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { | |
84 | wifi_state->STA_connected = true; | |
85 | wifi_state->STA_rssi = ap_info.rssi; | |
86 | xSemaphoreGive(xSemaphoreWiFi); | |
87 | } else { | |
88 | ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED"); | |
89 | } | |
90 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); | |
91 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); | |
92 | break; | |
93 | } | |
94 | ||
95 | case WIFI_EVENT_STA_DISCONNECTED: { | |
96 | ESP_LOGI(TAG, "Event STA disconnected"); | |
97 | // wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; | |
98 | // ESP_LOGI(TAG, "Event STA disconnected, reason:%d", disconnected->reason); | |
99 | if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { | |
100 | wifi_state->STA_connected = false; | |
101 | wifi_state->STA_online = false; | |
102 | xSemaphoreGive(xSemaphoreWiFi); | |
103 | } else { | |
104 | ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED"); | |
105 | } | |
7
2b337dd92f25
Added volts/current loop calculations. Added millis() timer running on the hardware clock. Completed most of the main state loop. Added MQTT wait for disconnect. MQTT disconnect in two passes, disconnect and stop.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
106 | if (ready_mqtt()) |
2b337dd92f25
Added volts/current loop calculations. Added millis() timer running on the hardware clock. Completed most of the main state loop. Added MQTT wait for disconnect. MQTT disconnect in two passes, disconnect and stop.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
107 | connect_mqtt(false); |
4 | 108 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); |
109 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); | |
110 | break; | |
111 | } | |
112 | ||
113 | default: | |
114 | ESP_LOGW(TAG, "Unknown WiFi event %d", (int)event_id); | |
115 | break; | |
116 | } | |
117 | } | |
118 | ||
119 | ||
120 | ||
121 | static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) | |
122 | { | |
123 | switch (event_id) { | |
124 | ||
125 | case IP_EVENT_STA_GOT_IP: | |
6
bad3414f7bc4
Added the getTempBaro and getVoltsCurrent functions to process the measured data. Added some main task code. Added subscribe to MQTT events.
Michiel Broek <mbroek@mbse.eu>
parents:
5
diff
changeset
|
126 | //ESP_LOGE(TAG, "got_ip_event_handler()"); |
4 | 127 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP); |
128 | ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; | |
129 | if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { | |
130 | wifi_state->STA_online = true; | |
131 | snprintf(wifi_state->STA_ip, 16, IPSTR, IP2STR(&event->ip_info.ip)); | |
132 | snprintf(wifi_state->STA_nm, 16, IPSTR, IP2STR(&event->ip_info.netmask)); | |
133 | snprintf(wifi_state->STA_gw, 16, IPSTR, IP2STR(&event->ip_info.gw)); | |
134 | xSemaphoreGive(xSemaphoreWiFi); | |
135 | } else { | |
136 | ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP"); | |
137 | } | |
5
b1f38105ca7e
Added task MQTT and some utilities. Added more power measurement variables and code. INA219 measurements are saved in the State record.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
138 | connect_mqtt(true); |
4 | 139 | break; |
140 | ||
141 | case IP_EVENT_STA_LOST_IP: | |
142 | ESP_LOGW(TAG, "Lost IP address"); | |
143 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP); | |
144 | if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { | |
145 | wifi_state->STA_ip[0] = '\0'; | |
146 | wifi_state->STA_nm[0] = '\0'; | |
147 | wifi_state->STA_gw[0] = '\0'; | |
148 | wifi_state->STA_online = false; | |
149 | xSemaphoreGive(xSemaphoreWiFi); | |
150 | } else { | |
151 | ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP"); | |
152 | } | |
9
1659bd3c7a2b
Added task_out to drive the relays and led lights. Added NVS namespace to store the state of the outputs. Respond to subscribed MQTT topics to set new output values.
Michiel Broek <mbroek@mbse.eu>
parents:
8
diff
changeset
|
153 | if (ready_mqtt()) |
1659bd3c7a2b
Added task_out to drive the relays and led lights. Added NVS namespace to store the state of the outputs. Respond to subscribed MQTT topics to set new output values.
Michiel Broek <mbroek@mbse.eu>
parents:
8
diff
changeset
|
154 | connect_mqtt(false); |
4 | 155 | break; |
156 | ||
157 | default: | |
158 | ESP_LOGW(TAG, "Unknown IP event %d", (int)event_id); | |
159 | break; | |
160 | } | |
161 | } | |
162 | ||
163 | ||
164 | ||
165 | void task_wifi( void * pvParameters ) | |
166 | { | |
167 | ESP_LOGI(TAG, "Start WiFi"); | |
168 | ||
169 | /* event handler and event group for the wifi driver */ | |
170 | xEventGroupWifi = xEventGroupCreate(); | |
171 | /* initialize the tcp stack */ | |
172 | ESP_ERROR_CHECK(esp_netif_init()); | |
173 | ESP_ERROR_CHECK(esp_event_loop_create_default()); | |
174 | sta_netif = esp_netif_create_default_wifi_sta(); | |
175 | assert(sta_netif); | |
176 | ||
177 | /* | |
178 | * memory allocation of objects used by the task | |
179 | */ | |
180 | xSemaphoreWiFi = xSemaphoreCreateMutex(); | |
181 | wifi_state = malloc(sizeof(WIFI_State)); | |
182 | memset(wifi_state, 0x00, sizeof(WIFI_State)); | |
183 | sprintf(wifi_state->STA_ssid, "%s", ESP_WIFI_SSID); | |
184 | ||
185 | /* | |
186 | * init wifi as station | |
187 | */ | |
188 | wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); | |
189 | ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); | |
190 | ||
191 | esp_event_handler_instance_t instance_any_id; | |
192 | esp_event_handler_instance_t instance_got_ip; | |
193 | ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id) ); | |
194 | ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, /*IP_EVENT_STA_GOT_IP*/ ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance_got_ip) ); | |
195 | ||
196 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); | |
197 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_Config) ); | |
198 | ESP_ERROR_CHECK(esp_wifi_start()); | |
199 | ||
200 | //xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); | |
201 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); | |
202 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); | |
203 | EventBits_t uxBits; | |
204 | ||
205 | ESP_LOGI(TAG, "Startup completed, enter task loop"); | |
206 | ||
207 | for(;;) { | |
208 | ||
209 | /* actions that can trigger: request a connection or a disconnection */ | |
210 | uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_STA_DISCONNECT, | |
211 | pdFALSE, pdFALSE, portMAX_DELAY ); | |
212 | ||
213 | if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) { | |
214 | /* | |
215 | * user requested a disconnect, this will in effect disconnect the wifi | |
216 | */ | |
7
2b337dd92f25
Added volts/current loop calculations. Added millis() timer running on the hardware clock. Completed most of the main state loop. Added MQTT wait for disconnect. MQTT disconnect in two passes, disconnect and stop.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
217 | ESP_LOGI(TAG, "Request STA disconnect"); |
5
b1f38105ca7e
Added task MQTT and some utilities. Added more power measurement variables and code. INA219 measurements are saved in the State record.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
218 | connect_mqtt(false); |
7
2b337dd92f25
Added volts/current loop calculations. Added millis() timer running on the hardware clock. Completed most of the main state loop. Added MQTT wait for disconnect. MQTT disconnect in two passes, disconnect and stop.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
219 | wait_mqtt(10000); |
4 | 220 | ESP_ERROR_CHECK(esp_wifi_disconnect()); |
221 | xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); | |
222 | ||
223 | /* finally: release the request bit */ | |
224 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); | |
225 | ||
226 | } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) { | |
227 | ||
228 | ESP_LOGI(TAG, "Request STA connect `%s' `%s'", wifi_Config.sta.ssid, wifi_Config.sta.password); | |
229 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); | |
230 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_Config)); | |
231 | ||
232 | esp_err_t wifierror = esp_wifi_connect(); | |
233 | if (wifierror != ESP_OK) { | |
234 | ESP_LOGE(TAG, "esp_wifi_connect() rc=%04x", (int)wifierror); | |
235 | xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); | |
236 | } else { | |
237 | ESP_LOGI(TAG, "Connected Ok"); | |
238 | } | |
239 | ||
240 | /* | |
241 | * 3 scenarios here: connection is successful and TASK_WIFI_STA_CONNECTED will be posted | |
242 | * or it's a failure and we get a TASK_WIFI_STA_FAILED with a reason code. | |
243 | * Or, option 3, the 5 seconds timeout is reached. This happens when the AP is not in range. | |
244 | * Note that the reason code is not exploited. For all intent and purposes a failure is a failure. | |
245 | */ | |
246 | uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS); | |
247 | ||
248 | if (uxBits & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED)) { | |
249 | /* | |
250 | * only save the config if the connection was successful! | |
251 | */ | |
252 | if (uxBits & TASK_WIFI_STA_CONNECTED) { | |
253 | /* save wifi config */ | |
254 | //SaveStaConfig(); | |
255 | } else { | |
256 | ESP_LOGI(TAG, "No AP found"); | |
257 | vTaskDelay(3000 / portTICK_PERIOD_MS); | |
258 | ESP_LOGW(TAG, "Connection failed"); | |
259 | /* failed attempt to connect regardles of the reason */ | |
260 | ||
261 | /* otherwise: reset the config */ | |
262 | //memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); | |
263 | } | |
264 | } | |
265 | ||
266 | /* finally: release the request bit */ | |
267 | xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); | |
268 | } | |
269 | ||
270 | } /* for(;;) */ | |
271 | vTaskDelay(10 / portTICK_PERIOD_MS); | |
272 | } | |
273 | ||
274 |