1 /* MeshLink-tiny Example */
4 typedef void *ListItem_t;
7 #include "freertos/FreeRTOS.h"
8 #include "freertos/task.h"
9 #include "freertos/event_groups.h"
10 #include "esp_system.h"
12 #include "esp_event.h"
14 #include "esp_console.h"
15 #include "esp_vfs_dev.h"
16 #include "driver/uart.h"
17 #include "linenoise/linenoise.h"
18 #include "argtable3/argtable3.h"
20 #include "nvs_flash.h"
25 #include "meshlink-tiny.h"
27 /* The examples use WiFi configuration that you can set via project configuration menu
29 If you'd rather not, just change the below entries to strings with
30 the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
32 #define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
33 #define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
34 #define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
36 /* FreeRTOS event group to signal when we are connected*/
37 static EventGroupHandle_t s_wifi_event_group;
39 /* The event group allows multiple bits for each event, but we only care about two events:
40 * - we are connected to the AP with an IP
41 * - we failed to connect after the maximum amount of retries */
42 #define WIFI_CONNECTED_BIT BIT0
43 #define WIFI_FAIL_BIT BIT1
45 static const char *TAG = "wifi station";
47 static int s_retry_num = 0;
49 static void event_handler(void *arg, esp_event_base_t event_base,
50 int32_t event_id, void *event_data) {
51 if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
53 } else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
54 if(s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
57 ESP_LOGI(TAG, "retry to connect to the AP");
59 xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
62 ESP_LOGI(TAG, "connect to the AP fail");
63 } else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
64 ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
65 ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
67 xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
71 void wifi_init_sta(void) {
72 s_wifi_event_group = xEventGroupCreate();
76 ESP_ERROR_CHECK(esp_event_loop_create_default());
78 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
79 ESP_ERROR_CHECK(esp_wifi_init(&cfg));
81 ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
82 ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
84 wifi_config_t wifi_config = {
86 .ssid = EXAMPLE_ESP_WIFI_SSID,
87 .password = EXAMPLE_ESP_WIFI_PASS
91 /* Setting a password implies station will connect to all security modes including WEP/WPA.
92 * However these modes are deprecated and not advisable to be used. Incase your Access point
93 * doesn't support WPA2, these mode can be enabled by commenting below line */
95 if(strlen((char *)wifi_config.sta.password)) {
96 wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
99 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
100 ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
101 ESP_ERROR_CHECK(esp_wifi_start());
103 ESP_LOGI(TAG, "wifi_init_sta finished.");
105 /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
106 * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
107 EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
108 WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
113 /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
115 if(bits & WIFI_CONNECTED_BIT) {
116 ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
117 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
118 } else if(bits & WIFI_FAIL_BIT) {
119 ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
120 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
122 ESP_LOGE(TAG, "UNEXPECTED EVENT");
125 ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
126 ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
127 vEventGroupDelete(s_wifi_event_group);
131 static void mlt_log(meshlink_handle_t *mesh, meshlink_log_level_t leve, const char *text) {
132 ESP_LOGI(TAG, "Log: %s", text);
135 meshlink_handle_t *mesh = NULL;
137 static void receive(meshlink_handle_t *mesh, meshlink_node_t *from, const void *data, size_t len) {
138 char *str = (char *)data;
140 ESP_LOGI(TAG, "%s says: %s", from->name, str);
143 static int join_func(int argc, char **argv) {
148 if(!meshlink_join(mesh, argv[1])) {
149 ESP_LOGE(TAG, "Join failed");
153 ESP_LOGI(TAG, "Join completed");
155 meshlink_set_receive_cb(mesh, receive);
157 if(!meshlink_start(mesh)) {
158 ESP_LOGE(TAG, "Could not start mesh!");
165 static int say_func(int argc, char **argv) {
170 meshlink_node_t *peer = meshlink_get_node(mesh, argv[1]);
173 ESP_LOGE(TAG, "Peer not found");
177 if(!meshlink_send(mesh, peer, argv[2], strlen(argv[2]) + 1)) {
178 ESP_LOGE(TAG, "Send failed");
185 static int quit_func(int argc, char **argv) {
186 meshlink_close(mesh);
188 ESP_LOGI(TAG, "Closed mesh");
192 static void mlt_main(void) {
193 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, mlt_log);
195 ESP_LOGI(TAG, "Starting MeshLink-tiny instance...");
196 mesh = meshlink_open_ephemeral("esp32", "chat", DEV_CLASS_PORTABLE);
199 ESP_LOGE(TAG, "Open failed!");
203 esp_console_cmd_t join_cmd = {
205 .help = "Join a mesh",
209 esp_console_cmd_t say_cmd = {
211 .help = "Say something",
215 esp_console_cmd_t quit_cmd = {
221 esp_console_cmd_register(&join_cmd);
222 esp_console_cmd_register(&say_cmd);
223 esp_console_cmd_register(&quit_cmd);
224 esp_console_register_help_command();
227 char *line = linenoise("> ");
233 linenoiseHistoryAdd(line);
235 esp_console_run(line, &ret);
239 ESP_LOGI(TAG, "App quit");
240 esp_console_deinit();
243 static void initialize_nvs() {
244 esp_err_t err = nvs_flash_init();
246 if(err == ESP_ERR_NVS_NO_FREE_PAGES) {
247 ESP_ERROR_CHECK(nvs_flash_erase());
248 err = nvs_flash_init();
251 ESP_ERROR_CHECK(err);
254 static void initialize_console() {
255 /* Disable buffering on stdin */
256 setvbuf(stdin, NULL, _IONBF, 0);
258 /* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
259 esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
260 /* Move the caret to the beginning of the next line on '\n' */
261 esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
263 /* Configure UART. Note that REF_TICK is used so that the baud rate remains
264 * correct while APB frequency is changing in light sleep mode.
266 uart_config_t uart_config = {
267 .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
268 .data_bits = UART_DATA_8_BITS,
269 .parity = UART_PARITY_DISABLE,
270 .stop_bits = UART_STOP_BITS_1,
272 ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config));
274 /* Install UART driver for interrupt-driven reads and writes */
275 ESP_ERROR_CHECK(uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM,
276 256, 0, 0, NULL, 0));
278 /* Tell VFS to use UART driver */
279 esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
281 /* Initialize the console */
282 esp_console_config_t console_config = {
283 .max_cmdline_args = 8,
284 .max_cmdline_length = 256,
285 #if CONFIG_LOG_COLORS
286 .hint_color = atoi(LOG_COLOR_CYAN)
289 ESP_ERROR_CHECK(esp_console_init(&console_config));
293 void app_main(void) {
294 /* Print chip information */
295 esp_chip_info_t chip_info;
296 esp_chip_info(&chip_info);
297 printf("This is ESP8266 chip with %d CPU cores, WiFi, ",
300 printf("silicon revision %d, ", chip_info.revision);
302 printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
303 (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
306 initialize_console();
308 esp_console_register_help_command();
310 ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");