/****************************************************************************** * 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_SLAVE /******************************************************************************* * open AS_STA to compile sta test code * open AS_AP to compile ap test code * don't open both * ****************************************************************************/ #define AS_AP #define AP_SSID "MyIoTDemo" #define AP_PASSWORD "12345678" #define PWLDEV_ESP_NOW_CHANNEL_NUM 1 // wifi socket v1.0 2015-10-14 #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; LOCAL uint8 ap_channel = 1; static u8 simple_pair_stat = 0; static u8 esp_now_stat = 0; /* 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_AP /* since the ex_key transfer from AP to STA, so AP's ex_key must be set */ static u8 ex_key[16] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; #endif /* AS_AP */ 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); } void ICACHE_FLASH_ATTR sp_status(u8 *sa, u8 status) { #ifdef AS_AP if(sa) os_printf("Simple Pair: from " MACSTR "\n", MAC2STR(sa)); switch (status) { case SP_ST_AP_FINISH: simple_pair_get_peer_ref(NULL, NULL, ex_key); os_printf("Simple Pair: AP FINISH\n"); /* TODO: Wait STA use the ex-key communicate with AP, for example use ESP-NOW */ os_printf("SP_ST_STA_FINISH @t %d\n", system_get_time()); if(esp_now_stat) { if(esp_now_add_peer(sa, ESP_NOW_ROLE_CONTROLLER, 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 controller."); // 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_AP_RECV_NEG: /* AP recv a STA's negotiate request */ os_printf("Simple Pair: Recv STA Negotiate Request\n"); /* set peer must be called, because the simple pair need to know what peer mac is */ simple_pair_set_peer_ref(sa, tmpkey, ex_key); /* TODO:In this phase, the AP can interaction with Smart Phone, if the Phone agree, call start_neg or refuse */ simple_pair_ap_start_negotiate(); //simple_pair_ap_refuse_negotiate(); /* TODO:if refuse, maybe call simple_pair_deinit() to ending the simple pair */ break; case SP_ST_WAIT_TIMEOUT: /* In negotiate, timeout , so re-enter in to announce mode*/ os_printf("Simple Pair: Neg Timeout\n"); os_printf(" @t %d\n", system_get_time()); simple_pair_state_reset(); simple_pair_ap_enter_announce_mode(); 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_AP */ } LOCAL void ICACHE_FLASH_ATTR slave_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 slave_start_simple_pair(void) { int ret; #ifdef AS_AP 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: AP Enter Announce Mode ...\n"); /* ap must enter announce mode , so the sta can know which ap is ready to simple pair */ ret = simple_pair_ap_enter_announce_mode(); if (ret) { os_printf("Simple Pair: AP Enter Announce Mode Error, %d\n", ret); // return; goto WAIT_PAIR; } simple_pair_stat = 3; WAIT_PAIR: os_timer_disarm(&dev_espnow_timer); os_timer_setfn(&dev_espnow_timer, (os_timer_func_t *)slave_simple_pair_time_cb, NULL); os_timer_arm(&dev_espnow_timer, 30000, 0); #endif } 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) { slave_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_SLAVE) == 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"); } } /****************************************************************************** * FunctionName : user_set_softap_config * Description : set SSID and password of ESP8266 softAP * Parameters : none * Returns : none *******************************************************************************/ void ICACHE_FLASH_ATTR user_set_softap_config(void) { struct softap_config config; if(wifi_get_opmode() != SOFTAP_MODE) wifi_set_opmode(SOFTAP_MODE); os_memset(&config, 0, sizeof(config)); wifi_softap_get_config(&config); // Get config first. os_sprintf(config.ssid, AP_SSID); os_sprintf(config.password, AP_PASSWORD); config.ssid_len = os_strlen(config.ssid); config.authmode = AUTH_WPA_WPA2_PSK; config.channel = ap_channel; config.beacon_interval = 100; config.max_connection = 4; // how many stations can connect to ESP8266 softAP at most. wifi_softap_set_config(&config);// Set ESP8266 softap config . } LOCAL void ICACHE_FLASH_ATTR slave_key_long_press(void) { os_printf("%s\n", __FUNCTION__); slave_start_simple_pair(); } LOCAL void ICACHE_FLASH_ATTR slave_key_short_press(void) { os_printf("%s\n", __FUNCTION__); ap_channel = (ap_channel+1)%12; if(ap_channel == 0) ap_channel = 12; user_set_softap_config(); 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, slave_key_long_press, slave_key_short_press); keys.key_num = KEY_NUM; keys.single_key = single_key; key_init(&keys); user_set_softap_config(); system_init_done_cb(init_done); } #endif // ESPNOW_SLAVE device