参考:https://blog.youkuaiyun.com/qq_28877125/article/details/62319191
使用WiFi进行联网操作
整体调用的架构
1.获取wifi当前的工作模式
wifi的工作模式:
第一种:STA模式
任何一种无线网卡都可以运行在此模式下,这种模式也可以称为默认模式。在此模式下,无线网卡发送连接与认证消息给热点,热点接收到后完成认证后,发回成功认证消息,此网卡接入无线网络。这种模式下,wifi工作于从模式
第二种:AccessPoint模式
在一个无线网络环境中,无线热点是作为一个主设备,工作于主模式(Master mode)。通过管理控制可控制的STA,从而组成无线网络,也有相应的安全控制策略。由AP形成的网络,由AP的MAC地址唯一识别。热点完成创建后,会由热点创建一个被别的设备可识别的名称,称为SSID。在Linux下,要使用AP模式,必须使系统支持hostapd。
代码:
//获取wifi的工作模式
opmode = wifi_get_opmode();
os_printf(“\r\n 当前模式为:%d\r\n”,opmode);
现象:
2.设置wifi的工作模式
代码
//设置wifi的工作模式
opmode_error = wifi_set_opmode (0x03);
if(false == opmode_error)
{
os_printf(“set error\r\n”);
}
3.扫描所有附近所有的AP
system_init_done_cb(to_scan);//等到系统完成初始化就扫描
void to_scan(void)
{
wifi_station_scan(NULL,scan_done);
}
参考AT固件源码实现
void ICACHE_FLASH_ATTR
scan_done(void *arg,STATUS status)
{
char ssid[33] = "MEIZU";
char password[64] = "21103690";
char temp[128];
if (status == OK)
{
struct bss_info *bss_link = (struct bss_info *)arg;
bss_link = bss_link->next.stqe_next;//ignore first
while (bss_link != NULL)
{
os_memset(ssid, 0, 33);
if (os_strlen(bss_link->ssid) <= 32)
{
os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
}
else
{
os_memcpy(ssid, bss_link->ssid, 32);
}
os_sprintf(temp,"+CWLAP:(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",
bss_link->authmode, ssid, bss_link->rssi,
MAC2STR(bss_link->bssid),bss_link->channel);
os_printf("%s",temp);
bss_link = bss_link->next.stqe_next;
}
}
else
{
// os_sprintf(temp,"err, scan status %d\r\n", status);
// uart0_sendStr(temp);
os_printf("%s","Error");
}
}
4.连接某一个路由
//扫描完成以后就开始连接WiFi了
os_memcpy(&stationConf.ssid,ssid, 32);//WiFi名字加入到配置中去
os_memcpy(&stationConf.password,password,64);//WiFi密码加入到配置中去
wifi_station_set_config_current(&stationConf);//将设置好的配置加入到配置函数中去
wifi_station_connect();//在非user_init()入口函数中连接WiFi,需要调用这个函数
5.定时扫描
os_timer_setfn(&connect_timer,Wifi_conned,NULL);//调用自己写的WiFi连接函数
os_timer_arm(&connect_timer,2000,1);//设置连接WiFi定时器
其他一些知识
ICACHE_FLASH_ATTR
添加了这个宏的函数就会存放到ROM里面去,CPU仅在调用的时候才将它们读到cache(缓存)中运行,没有添加这个宏的函数将一开始上电就运行在RAM中;由于模块的空间有限,我们无法将所有的代码都一次性加载到RAM中去运行,因此在大部分函数前添加这个特殊的宏。
需要注意的是不要在GPIO或UART中断处理函数中调用带有“ICACHE_FLASH_ATTR”宏的函数,否则将引起异常
整个user_main.c的代码
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "user_devicefind.h"
#include "user_webserver.h"
#if ESP_PLATFORM
#include "user_esp_platform.h"
#endif
uint32 priv_param_start_sec;
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
os_timer_t connect_timer;
struct station_config stationConf;
void ICACHE_FLASH_ATTR
Wifi_conned(void *arg)
{
static uint8 count=0;
uint8 status;
os_timer_disarm(&connect_timer);
count++;
status=wifi_station_get_connect_status();
if(status==STATION_GOT_IP){
os_printf("Wifi connect success!");
return;
}else{
if(count>=7){
os_printf("Wifi connect fail!");
return;
}
}
os_timer_arm(&connect_timer,2000,1);
}
void ICACHE_FLASH_ATTR
scan_done(void *arg,STATUS status)
{
char ssid[33] = "MEIZU";
char password[64] = "21103690";
char temp[128];
if (status == OK)
{
struct bss_info *bss_link = (struct bss_info *)arg;
bss_link = bss_link->next.stqe_next;//ignore first
while (bss_link != NULL)
{
os_memset(ssid, 0, 33);
if (os_strlen(bss_link->ssid) <= 32)
{
os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
}
else
{
os_memcpy(ssid, bss_link->ssid, 32);
}
os_sprintf(temp,"+CWLAP:(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",
bss_link->authmode, ssid, bss_link->rssi,
MAC2STR(bss_link->bssid),bss_link->channel);
os_printf("%s",temp);
bss_link = bss_link->next.stqe_next;
}
//扫描完成以后就开始连接WiFi了
os_memcpy(&stationConf.ssid,ssid, 32);//WiFi名字加入到配置中去
os_memcpy(&stationConf.password,password,64);//WiFi密码加入到配置中去
wifi_station_set_config_current(&stationConf);//将设置好的配置加入到配置函数中去
wifi_station_connect();//在非user_init()入口函数中连接WiFi,需要调用这个函数
os_timer_setfn(&connect_timer,Wifi_conned,NULL);//调用自己写的WiFi连接函数
os_timer_arm(&connect_timer,2000,1);//设置连接WiFi定时器
}
else
{
// os_sprintf(temp,"err, scan status %d\r\n", status);
// uart0_sendStr(temp);
os_printf("%s","Error");
}
}
void to_scan(void)
{
wifi_station_scan(NULL,scan_done);
}
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
priv_param_start_sec = 0x3C;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_16M_MAP_512_512:
rf_cal_sec = 512 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_32M_MAP_512_512:
rf_cal_sec = 1024 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
priv_param_start_sec = 0xFC;
break;
default:
rf_cal_sec = 0;
priv_param_start_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
uint8 opmode;
uint8 opmode_error;
uart_init(115200,115200);
// uart0_sendStr("\r\nhello world\r\n");
//获取wifi的工作模式
opmode = wifi_get_opmode();
os_printf("\r\n 当前模式为:%d\r\n",opmode);
//设置wifi的工作模式
opmode_error = wifi_set_opmode (0x03);
if(false == opmode_error)
{
os_printf("set error\r\n");
}
//获取wifi的工作模式
// opmode = wifi_get_opmode();
// os_printf("\r\n 当前模式为:%d\r\n",opmode);
//获取AP信息
system_init_done_cb(to_scan);//等到系统完成初始化就扫描
// os_printf("hello i am liangjia\r\n");
// os_printf("SDK version:%s\n", system_get_sdk_version());
// os_printf("hello i am liangjia\r\n");
#if ESP_PLATFORM
/*Initialization of the peripheral drivers*/
/*For light demo , it is user_light_init();*/
/* Also check whether assigned ip addr by the router.If so, connect to ESP-server */
user_esp_platform_init();
#endif
/*Establish a udp socket to receive local device detect info.*/
/*Listen to the port 1025, as well as udp broadcast.
/*If receive a string of device_find_request, it rely its IP address and MAC.*/
user_devicefind_init();
/*Establish a TCP server for http(with JSON) POST or GET command to communicate with the device.*/
/*You can find the command in "2B-SDK-Espressif IoT Demo.pdf" to see the details.*/
/*the JSON command for curl is like:*/
/*3 Channel mode: curl -X POST -H "Content-Type:application/json" -d "{\"period\":1000,\"rgb\":{\"red\":16000,\"green\":16000,\"blue\":16000}}" http://192.168.4.1/config?command=light */
/*5 Channel mode: curl -X POST -H "Content-Type:application/json" -d "{\"period\":1000,\"rgb\":{\"red\":16000,\"green\":16000,\"blue\":16000,\"cwhite\":3000,\"wwhite\",3000}}" http://192.168.4.1/config?command=light */
#ifdef SERVER_SSL_ENABLE
user_webserver_init(SERVER_SSL_PORT);
#else
user_webserver_init(SERVER_PORT);
#endif
}
实验现象:
用手机开一个热点先