]> granicus.if.org Git - esp-idf/blob - examples/mesh/manual_networking/main/mesh_main.c
mesh: use new event library
[esp-idf] / examples / mesh / manual_networking / main / mesh_main.c
1 /* Mesh Manual Networking Example
2
3    This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5    Unless required by applicable law or agreed to in writing, this
6    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7    CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <string.h>
10 #include "esp_wifi.h"
11 #include "esp_system.h"
12 #include "esp_event.h"
13 #include "esp_log.h"
14 #include "esp_mesh.h"
15 #include "esp_mesh_internal.h"
16 #include "mesh_light.h"
17 #include "nvs_flash.h"
18
19 /*******************************************************
20  *                Macros
21  *******************************************************/
22 //#define MESH_SET_ROOT
23
24 #ifndef MESH_SET_ROOT
25 #define MESH_SET_NODE
26 #endif
27
28 /*******************************************************
29  *                Constants
30  *******************************************************/
31
32 /*******************************************************
33  *                Variable Definitions
34  *******************************************************/
35 static const char *MESH_TAG = "mesh_main";
36 static const uint8_t MESH_ID[6] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77};
37 static mesh_addr_t mesh_parent_addr;
38 static int mesh_layer = -1;
39
40 /*******************************************************
41  *                Function Declarations
42  *******************************************************/
43 void mesh_scan_done_handler(int num);
44
45 /*******************************************************
46  *                Function Definitions
47  *******************************************************/
48 void mesh_scan_done_handler(int num)
49 {
50     int i;
51     int ie_len = 0;
52     mesh_assoc_t assoc;
53     mesh_assoc_t parent_assoc = { .layer = CONFIG_MESH_MAX_LAYER, .rssi = -120 };
54     wifi_ap_record_t record;
55     wifi_ap_record_t parent_record = { 0, };
56     bool parent_found = false;
57     mesh_type_t my_type = MESH_IDLE;
58     int my_layer = -1;
59     wifi_config_t parent = { 0, };
60     wifi_scan_config_t scan_config = { 0 };
61
62     for (i = 0; i < num; i++) {
63         esp_mesh_scan_get_ap_ie_len(&ie_len);
64         esp_mesh_scan_get_ap_record(&record, &assoc);
65         if (ie_len == sizeof(assoc)) {
66             ESP_LOGW(MESH_TAG,
67                      "<MESH>[%d]%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d, ID<"MACSTR"><%s>",
68                      i, record.ssid, assoc.layer, assoc.layer_cap, assoc.assoc,
69                      assoc.assoc_cap, assoc.layer2_cap, MAC2STR(record.bssid),
70                      record.primary, record.rssi, MAC2STR(assoc.mesh_id), assoc.encrypted ? "IE Encrypted" : "IE Unencrypted");
71
72 #ifdef MESH_SET_NODE
73             if (assoc.mesh_type != MESH_IDLE && assoc.layer_cap
74                     && assoc.assoc < assoc.assoc_cap && record.rssi > -70) {
75                 if (assoc.layer < parent_assoc.layer || assoc.layer2_cap < parent_assoc.layer2_cap) {
76                     parent_found = true;
77                     memcpy(&parent_record, &record, sizeof(record));
78                     memcpy(&parent_assoc, &assoc, sizeof(assoc));
79                     if (parent_assoc.layer_cap != 1) {
80                         my_type = MESH_NODE;
81                     } else {
82                         my_type = MESH_LEAF;
83                     }
84                     my_layer = parent_assoc.layer + 1;
85                     break;
86                 }
87             }
88 #endif
89         } else {
90             ESP_LOGI(MESH_TAG, "[%d]%s, "MACSTR", channel:%u, rssi:%d", i,
91                      record.ssid, MAC2STR(record.bssid), record.primary,
92                      record.rssi);
93 #ifdef MESH_SET_ROOT
94             if (!strcmp(CONFIG_MESH_ROUTER_SSID, (char *) record.ssid)) {
95                 parent_found = true;
96                 memcpy(&parent_record, &record, sizeof(record));
97                 my_type = MESH_ROOT;
98                 my_layer = MESH_ROOT_LAYER;
99             }
100 #endif
101         }
102     }
103     esp_mesh_flush_scan_result();
104     if (parent_found) {
105         /*
106          * parent
107          * Both channel and SSID of the parent are mandatory.
108          */
109         parent.sta.channel = parent_record.primary;
110         memcpy(&parent.sta.ssid, &parent_record.ssid,
111                sizeof(parent_record.ssid));
112         parent.sta.bssid_set = 1;
113         memcpy(&parent.sta.bssid, parent_record.bssid, 6);
114         ESP_ERROR_CHECK(esp_mesh_set_ap_authmode(parent_record.authmode));
115         if (my_type == MESH_ROOT) {
116             if (parent_record.authmode != WIFI_AUTH_OPEN) {
117                 memcpy(&parent.sta.password, CONFIG_MESH_ROUTER_PASSWD,
118                        strlen(CONFIG_MESH_ROUTER_PASSWD));
119             }
120             ESP_LOGW(MESH_TAG, "<PARENT>%s, "MACSTR", channel:%u, rssi:%d",
121                      parent_record.ssid, MAC2STR(parent_record.bssid),
122                      parent_record.primary, parent_record.rssi);
123         } else {
124             if (parent_record.authmode != WIFI_AUTH_OPEN) {
125                 memcpy(&parent.sta.password, CONFIG_MESH_AP_PASSWD,
126                        strlen(CONFIG_MESH_AP_PASSWD));
127             }
128             ESP_LOGW(MESH_TAG,
129                      "<PARENT>%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d",
130                      parent_record.ssid, parent_assoc.layer,
131                      parent_assoc.layer_cap, parent_assoc.assoc,
132                      parent_assoc.assoc_cap, parent_assoc.layer2_cap,
133                      MAC2STR(parent_record.bssid), parent_record.primary,
134                      parent_record.rssi);
135         }
136         ESP_ERROR_CHECK(esp_mesh_set_parent(&parent, (mesh_addr_t *)&parent_assoc.mesh_id, my_type, my_layer));
137
138     } else {
139         ESP_LOGW(MESH_TAG,
140                  "<Warning>no parent found, modify IE crypto configuration and scan");
141         if (CONFIG_MESH_IE_CRYPTO_FUNCS) {
142             /* modify IE crypto key */
143             ESP_LOGW(MESH_TAG, "<Config>modify IE crypto key to %s", CONFIG_MESH_IE_CRYPTO_KEY);
144             ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_funcs(&g_wifi_default_mesh_crypto_funcs));
145             ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_key(CONFIG_MESH_IE_CRYPTO_KEY, strlen(CONFIG_MESH_IE_CRYPTO_KEY)));
146         } else {
147             /* disable IE crypto */
148             ESP_LOGW(MESH_TAG, "<Config>disable IE crypto");
149             ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_funcs(NULL));
150         }
151         esp_wifi_scan_stop();
152         scan_config.show_hidden = 1;
153         scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
154         ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0));
155     }
156 }
157
158 void mesh_event_handler(void *arg, esp_event_base_t event_base,
159                         int32_t event_id, void *event_data)
160 {
161     mesh_addr_t id = {0,};
162     static uint8_t last_layer = 0;
163     wifi_scan_config_t scan_config = { 0 };
164
165     switch (event_id) {
166     case MESH_EVENT_STARTED: {
167         esp_mesh_get_id(&id);
168         ESP_LOGI(MESH_TAG, "<MESH_EVENT_STARTED>ID:"MACSTR"", MAC2STR(id.addr));
169         mesh_layer = esp_mesh_get_layer();
170         ESP_ERROR_CHECK(esp_mesh_set_self_organized(0, 0));
171         esp_wifi_scan_stop();
172         /* mesh softAP is hidden */
173         scan_config.show_hidden = 1;
174         scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
175         ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0));
176     }
177     break;
178     case MESH_EVENT_STOPPED: {
179         ESP_LOGI(MESH_TAG, "<MESH_EVENT_STOPPED>");
180         mesh_layer = esp_mesh_get_layer();
181     }
182     break;
183     case MESH_EVENT_CHILD_CONNECTED: {
184         mesh_event_child_connected_t *child_connected = (mesh_event_child_connected_t *)event_data;
185         ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHILD_CONNECTED>aid:%d, "MACSTR"",
186                  child_connected->aid,
187                  MAC2STR(child_connected->mac));
188     }
189     break;
190     case MESH_EVENT_CHILD_DISCONNECTED: {
191         mesh_event_child_disconnected_t *child_disconnected = (mesh_event_child_disconnected_t *)event_data;
192         ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHILD_DISCONNECTED>aid:%d, "MACSTR"",
193                  child_disconnected->aid,
194                  MAC2STR(child_disconnected->mac));
195     }
196     case MESH_EVENT_ROUTING_TABLE_ADD: {
197         mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)event_data;
198         ESP_LOGW(MESH_TAG, "<MESH_EVENT_ROUTING_TABLE_ADD>add %d, new:%d",
199                  routing_table->rt_size_change,
200                  routing_table->rt_size_new);
201     }
202     break;
203     case MESH_EVENT_ROUTING_TABLE_REMOVE: {
204         mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)event_data;
205         ESP_LOGW(MESH_TAG, "<MESH_EVENT_ROUTING_TABLE_REMOVE>remove %d, new:%d",
206                  routing_table->rt_size_change,
207                  routing_table->rt_size_new);
208     }
209     break;
210     case MESH_EVENT_NO_PARENT_FOUND: {
211         mesh_event_no_parent_found_t *no_parent = (mesh_event_no_parent_found_t *)event_data;
212         ESP_LOGI(MESH_TAG, "<MESH_EVENT_NO_PARENT_FOUND>scan times:%d",
213                  no_parent->scan_times);
214     }
215     /* TODO handler for the failure */
216     break;
217     case MESH_EVENT_PARENT_CONNECTED: {
218         mesh_event_connected_t *connected = (mesh_event_connected_t *)event_data;
219         esp_mesh_get_id(&id);
220         mesh_layer = connected->self_layer;
221         memcpy(&mesh_parent_addr.addr, connected->connected.bssid, 6);
222         ESP_LOGI(MESH_TAG,
223                  "<MESH_EVENT_PARENT_CONNECTED>layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR"",
224                  last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr),
225                  esp_mesh_is_root() ? "<ROOT>" :
226                  (mesh_layer == 2) ? "<layer2>" : "", MAC2STR(id.addr));
227         last_layer = mesh_layer;
228         mesh_connected_indicator(mesh_layer);
229         if (esp_mesh_is_root()) {
230             tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA);
231         }
232     }
233     break;
234     case MESH_EVENT_PARENT_DISCONNECTED: {
235         mesh_event_disconnected_t *disconnected = (mesh_event_disconnected_t *)event_data;
236         ESP_LOGI(MESH_TAG,
237                  "<MESH_EVENT_PARENT_DISCONNECTED>reason:%d",
238                  disconnected->reason);
239         mesh_disconnected_indicator();
240         mesh_layer = esp_mesh_get_layer();
241         if (disconnected->reason == WIFI_REASON_ASSOC_TOOMANY) {
242             esp_wifi_scan_stop();
243             scan_config.show_hidden = 1;
244             scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
245             ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0));
246         }
247     }
248     break;
249     case MESH_EVENT_LAYER_CHANGE: {
250         mesh_event_layer_change_t *layer_change = (mesh_event_layer_change_t *)event_data;
251         mesh_layer = layer_change->new_layer;
252         ESP_LOGI(MESH_TAG, "<MESH_EVENT_LAYER_CHANGE>layer:%d-->%d%s",
253                  last_layer, mesh_layer,
254                  esp_mesh_is_root() ? "<ROOT>" :
255                  (mesh_layer == 2) ? "<layer2>" : "");
256         last_layer = mesh_layer;
257         mesh_connected_indicator(mesh_layer);
258     }
259     break;
260     case MESH_EVENT_ROOT_ADDRESS: {
261         mesh_event_root_address_t *root_addr = (mesh_event_root_address_t *)event_data;
262         ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_ADDRESS>root address:"MACSTR"",
263                  MAC2STR(root_addr->addr));
264     }
265     break;
266     case MESH_EVENT_TODS_STATE: {
267         mesh_event_toDS_state_t *toDs_state = (mesh_event_toDS_state_t *)event_data;
268         ESP_LOGI(MESH_TAG, "<MESH_EVENT_TODS_REACHABLE>state:%d", *toDs_state);
269     }
270     break;
271     case MESH_EVENT_ROOT_FIXED: {
272         mesh_event_root_fixed_t *root_fixed = (mesh_event_root_fixed_t *)event_data;
273         ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_FIXED>%s",
274                  root_fixed->is_fixed ? "fixed" : "not fixed");
275     }
276     break;
277     case MESH_EVENT_SCAN_DONE: {
278         mesh_event_scan_done_t *scan_done = (mesh_event_scan_done_t *)event_data;
279         ESP_LOGI(MESH_TAG, "<MESH_EVENT_SCAN_DONE>number:%d",
280                  scan_done->number);
281         mesh_scan_done_handler(scan_done->number);
282     }
283     break;
284     default:
285         ESP_LOGI(MESH_TAG, "unknown id:%d", event_id);
286         break;
287     }
288 }
289
290 void ip_event_handler(void *arg, esp_event_base_t event_base,
291                       int32_t event_id, void *event_data)
292 {
293     ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
294     ESP_LOGI(MESH_TAG, "<IP_EVENT_STA_GOT_IP>IP:%s", ip4addr_ntoa(&event->ip_info.ip));
295 }
296
297 void app_main(void)
298 {
299     ESP_ERROR_CHECK(mesh_light_init());
300     ESP_ERROR_CHECK(nvs_flash_init());
301     /*  tcpip initialization */
302     tcpip_adapter_init();
303     /* for mesh
304      * stop DHCP server on softAP interface by default
305      * stop DHCP client on station interface by default
306      * */
307     ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
308     ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));
309     /*  event initialization */
310     ESP_ERROR_CHECK(esp_event_loop_create_default());
311     /*  wifi initialization */
312     wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
313     ESP_ERROR_CHECK(esp_wifi_init(&config));
314     ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
315     ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH));
316     ESP_ERROR_CHECK(esp_wifi_start());
317     /*  mesh initialization */
318     ESP_ERROR_CHECK(esp_mesh_init());
319     ESP_ERROR_CHECK(esp_event_handler_register(MESH_EVENT, ESP_EVENT_ANY_ID, &mesh_event_handler, NULL));
320     /* mesh enable IE crypto */
321     mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT();
322     /* mesh ID */
323     memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6);
324     /* router */
325     cfg.channel = CONFIG_MESH_CHANNEL;
326     cfg.router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID);
327     memcpy((uint8_t *) &cfg.router.ssid, CONFIG_MESH_ROUTER_SSID, cfg.router.ssid_len);
328     memcpy((uint8_t *) &cfg.router.password, CONFIG_MESH_ROUTER_PASSWD,
329            strlen(CONFIG_MESH_ROUTER_PASSWD));
330     /* mesh softAP */
331     ESP_ERROR_CHECK(esp_mesh_set_ap_authmode(CONFIG_MESH_AP_AUTHMODE));
332     cfg.mesh_ap.max_connection = CONFIG_MESH_AP_CONNECTIONS;
333     memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD,
334            strlen(CONFIG_MESH_AP_PASSWD));
335     ESP_ERROR_CHECK(esp_mesh_set_config(&cfg));
336     /* mesh start */
337     ESP_ERROR_CHECK(esp_mesh_start());
338     ESP_LOGI(MESH_TAG, "mesh starts successfully, heap:%d\n",  esp_get_free_heap_size());
339 }