/****************************************************************************** * Copyright 2013-2014 Espressif Systems (Wuxi) * * FileName: user_main.c * * Description: entry file of user application * * Modification history: * 2015/7/3, v1.0 create this file. *******************************************************************************/ #include "osapi.h" #include "user_interface.h" #include "driver/uart.h" #include "driver/key.h" #include "user_json.h" #include "espnow.h" #include "mem.h" #include "simple_pair.h" #if ESPNOW_CONTROLLER /******************************************************************************* * open AS_STA to compile sta test code * open AS_AP to compile ap test code * don't open both * ****************************************************************************/ #define AS_STA #define PWLDEV_ESP_NOW_CHANNEL_NUM 6 // based on spadev board #define KEY_NUM 1 #define KEY_0_IO_MUX PERIPHS_IO_MUX_MTDI_U #define KEY_0_IO_NUM 12 #define KEY_0_IO_FUNC FUNC_GPIO12 #define PWM_CHANNEL 1 #define LED_0_OUT_IO_MUX PERIPHS_IO_MUX_GPIO5_U #define LED_0_OUT_IO_NUM 5 #define LED_0_OUT_IO_FUNC FUNC_GPIO5 LOCAL struct keys_param keys; LOCAL struct single_key_param *single_key[KEY_NUM]; LOCAL os_timer_t dev_espnow_timer; static u8 simple_pair_stat = 0; static u8 esp_now_stat = 0; LOCAL uint8 ap_channel = 1; /* STA & AP use the same tmpkey to encrypt Simple Pair communication */ static u8 tmpkey[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; #ifdef AS_STA /* since the ex_key transfer from AP to STA, so STA's ex_key don't care */ static u8 ex_key[16] = {0x00}; #endif /* AS_STA */ void ICACHE_FLASH_ATTR show_key(u8 *buf, u8 len) { u8 i; for (i = 0; i < len; i++) os_printf("%02x,%s", buf[i], (i%16 == 15?"\n":" ")); } void ICACHE_FLASH_ATTR show_espnow_cnt(void) { u8 all_cnt, encrypt_cnt; if (esp_now_get_cnt_info(&all_cnt, &encrypt_cnt)) os_printf("get_cnt_info failed\r\n"); os_printf("client:%d, encrypted client:%d\r\n", all_cnt, encrypt_cnt); } #ifdef AS_STA static void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status) { int ret; if (status == OK) { struct bss_info *bss_link = (struct bss_info *)arg; while (bss_link != NULL) { if (bss_link->simple_pair) { os_printf("Simple Pair: bssid %02x:%02x:%02x:%02x:%02x:%02x Ready!\n", bss_link->bssid[0], bss_link->bssid[1], bss_link->bssid[2], bss_link->bssid[3], bss_link->bssid[4], bss_link->bssid[5]); os_printf("peer chn %d\n", bss_link->channel); simple_pair_set_peer_ref(bss_link->bssid, tmpkey, NULL); ret = simple_pair_sta_start_negotiate(); if (ret) os_printf("Simple Pair: STA start NEG Failed\n"); else os_printf("Simple Pair: STA start NEG OK\n"); break; } bss_link = bss_link->next.stqe_next; } } else { os_printf("err, scan status %d\n", status); } } #endif void ICACHE_FLASH_ATTR sp_status(u8 *sa, u8 status) { #ifdef AS_STA if(sa) os_printf("Simple Pair: sta " MACSTR "\n", MAC2STR(sa)); switch (status) { case SP_ST_STA_FINISH: simple_pair_get_peer_ref(NULL, NULL, ex_key); os_printf("Simple Pair: STA FINISH, Ex_key "); show_key(ex_key, 16); /* TODO: Try to use the ex-key communicate with AP, for example use ESP-NOW */ os_printf("SP_ST_STA_FINISH @t %ld\n", system_get_time()); if(esp_now_stat) { if(esp_now_add_peer(sa, ESP_NOW_ROLE_SLAVE, ap_channel, ex_key, 16) == 0) { os_printf("add remote peer addr success\n"); char *pbuf = NULL; pbuf = (char *)os_zalloc(jsonSize); os_sprintf(pbuf, "hello slave."); // json_ws_send((struct jsontree_value *)&set_pwl_tree, "light", pbuf); if (esp_now_send(sa, pbuf, os_strlen(pbuf))) os_printf("fail\r\n"); else os_printf("ok\r\n"); // EPIT_DBG("ctrl:%s\n", pbuf); os_free(pbuf); } show_espnow_cnt(); } /* if test ok , deinit simple pair */ simple_pair_deinit(); simple_pair_stat = 0; os_timer_disarm(&dev_espnow_timer); break; case SP_ST_STA_AP_REFUSE_NEG: /* AP refuse , so try simple pair again or scan other ap*/ os_printf("Simple Pair: Recv AP Refuse\n"); simple_pair_state_reset(); simple_pair_sta_enter_scan_mode(); wifi_station_scan(NULL, scan_done); break; case SP_ST_WAIT_TIMEOUT: /* In negotiate, timeout , so try simple pair again */ os_printf("Simple Pair: Neg Timeout\n"); os_printf(" @t %d\n", system_get_time()); simple_pair_state_reset(); simple_pair_sta_enter_scan_mode(); wifi_station_scan(NULL, scan_done); break; case SP_ST_SEND_ERROR: os_printf("Simple Pair: Send Error\n"); /* maybe the simple_pair_set_peer_ref() haven't called, it send to a wrong mac address */ break; case SP_ST_KEY_INSTALL_ERR: os_printf("Simple Pair: Key Install Error\n"); /* 1. maybe something argument error. 2. maybe the key number is full in system*/ /* TODO: Check other modules which use lots of keys Example: ESPNOW and STA/AP use lots of keys */ break; case SP_ST_KEY_OVERLAP_ERR: os_printf("Simple Pair: Key Overlap Error\n"); /* 1. maybe something argument error. 2. maybe the MAC Address is already use in ESP-NOW or other module the same MAC Address has multi key*/ /* TODO: Check if the same MAC Address used already, Example: del MAC item of ESPNOW or other module */ esp_now_del_peer(sa); break; case SP_ST_OP_ERROR: os_printf("Simple Pair: Operation Order Error\n"); /* 1. maybe the function call order has something wrong */ /* TODO: Adjust your function call order */ break; default: os_printf("Simple Pair: Unknown Error\n"); break; } #endif /* AS_STA */ } LOCAL void ICACHE_FLASH_ATTR ctrller_simple_pair_time_cb(void) { os_printf("%s\n", __FUNCTION__); os_timer_disarm(&dev_espnow_timer); if(simple_pair_stat) { simple_pair_deinit(); simple_pair_stat = 0; } } LOCAL void ICACHE_FLASH_ATTR ctrller_start_simple_pair(void) { int ret; #ifdef AS_STA os_printf("dev chn %d\n", wifi_get_channel()); os_printf(" @t %d\n", system_get_time()); // show_espnow_cnt(); if(simple_pair_stat) { simple_pair_deinit(); simple_pair_stat = 0; } /* init simple pair */ ret = simple_pair_init(); if (ret) { os_printf("Simple Pair: init error, %d\n", ret); // return; goto WAIT_PAIR; } simple_pair_stat = 1; /* register simple pair status callback function */ ret = register_simple_pair_status_cb(sp_status); if (ret) { os_printf("Simple Pair: register status cb error, %d\n", ret); // return; goto WAIT_PAIR; } simple_pair_stat = 2; os_printf("Simple Pair: STA Enter Scan Mode ...\n"); ret = simple_pair_sta_enter_scan_mode(); if (ret) { os_printf("Simple Pair: STA Enter Scan Mode Error, %d\n", ret); // return; goto WAIT_PAIR; } simple_pair_stat = 3; /* scan ap to searh which ap is ready to simple pair */ os_printf("Simple Pair: STA Scan AP ...\n"); wifi_station_scan(NULL,scan_done); #endif WAIT_PAIR: os_timer_disarm(&dev_espnow_timer); os_timer_setfn(&dev_espnow_timer, (os_timer_func_t *)ctrller_simple_pair_time_cb, NULL); os_timer_arm(&dev_espnow_timer, 30000, 0); } void esp_now_recv_cb(u8 *mac_addr, u8 *data, u8 len) { u8 all_cnt, encrypt_cnt; if (esp_now_get_cnt_info(&all_cnt, &encrypt_cnt)) os_printf("get_cnt_info failed\r\n"); os_printf("client:%d, encrypted client:%d\r\n", all_cnt, encrypt_cnt); os_printf("esp_now_recv_cb_t %d from " MACSTR "\n", len, MAC2STR(mac_addr)); data[len-1] = '\0'; os_printf("esp_now_recv_cb_date: %s\n",data); // user_printbuf(data, len, "nowin"); } void esp_now_send_cb(u8 *mac_addr, u8 status) { os_printf("esp_now_send_cb_t\n"); } void ICACHE_FLASH_ATTR init_done(void) { ctrller_start_simple_pair(); if(esp_now_init() == 0) { os_printf("esp_now_init ok\n"); esp_now_stat = 1; esp_now_register_recv_cb(esp_now_recv_cb); esp_now_register_send_cb(esp_now_send_cb); uint8 ch = PWLDEV_ESP_NOW_CHANNEL_NUM; wifi_set_channel(ch); ch = wifi_get_channel(); os_printf("wifi channel is %d\n",ch); if(esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER) == 0) os_printf("set myself as slave\n"); // u8 key[16]= {0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44}; // if(esp_now_add_peer(hwaddr, ESP_NOW_ROLE_CONTROLLER, ch, key, 16) == 0) // os_printf("add local peer addr success\n"); os_printf("esp config success\n"); } else { os_printf("esp_now_init fail\n"); } } LOCAL void ICACHE_FLASH_ATTR ctrller_key_long_press(void) { os_printf("%s\n", __FUNCTION__); ctrller_start_simple_pair(); } LOCAL void ICACHE_FLASH_ATTR ctrller_key_short_press(void) { os_printf("%s\n", __FUNCTION__); ap_channel = (ap_channel+1)%12; if(ap_channel == 0) ap_channel = 12; os_printf("set chn %d\n", ap_channel); } LOCAL void ICACHE_FLASH_ATTR device_io_init(void) { PIN_FUNC_SELECT(KEY_0_IO_MUX, KEY_0_IO_FUNC); PIN_FUNC_SELECT(LED_0_OUT_IO_MUX, LED_0_OUT_IO_FUNC); GPIO_OUTPUT_SET(GPIO_ID_PIN(LED_0_OUT_IO_NUM), 0); } void ICACHE_FLASH_ATTR device_init(void) { device_io_init(); single_key[0] = key_init_single(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC, ctrller_key_long_press, ctrller_key_short_press); keys.key_num = KEY_NUM; keys.single_key = single_key; key_init(&keys); #ifdef AS_STA wifi_set_opmode(STATION_MODE); #endif system_init_done_cb(init_done); } #endif // ESPNOW_CONTROLLER device