在上一篇博客中,我们已经完成了AP模式的设置和TCP的连接,现在我们接上篇继续往下讲下TCP连接后我们要做什么?

根据上篇所说,我这次开发ESP8266是为做智能家居,所以我们为了方便,我们不可能把ES8266所要连接写死在程序里,那我们要如何获取到WIFI的SSID和密码呢?

我们可以通过手机APP连接ESP8266发射出来的热点,手机作为客户端连接ESP8266服务端,通过TCP把SSID和密码发送给ESP8266,模块收到后切换成Station模式连接无线网络,同时手机APP连接相同的无线网络,建立UDP连接服务端,等待模块发送数据。这里为方便解析,统一数据格式,模块和APP都是采用的JSON数据格式。对了,至于手机APP这个后面我尽量也出个教程简单说下,后面我看下有空先把APK 先放上来。

好了,我们现在来看下模块收到JSON数据后要怎么处理:这部分程序我们都是在TCP接收回调函数里处理的

cJSON *ssid_json,*psw_json,*type_json,*mac_json;

 cJSON *root = cJSON_Parse(pdata);
 if(!root){   //不符合JSON格式
  os_printf("Error before: [%s]\n",cJSON_GetErrorPtr());
  cJSON *Result = cJSON_CreateObject();
  cJSON_AddNumberToObject(Result,"status",3);
  cJSON_AddStringToObject(Result,"msg","json error");
  char *succeedData = cJSON_Print(Result);
  char data[1024];
  os_sprintf(data,"%s",succeedData);
  espconn_send((struct espconn *)arg,data,strlen(data));
 }else{
  char *ssid,*psw;
  int state;
  os_printf("接收成功");
  //解析字段
  cJSON *state_json = cJSON_GetObjectItem(root,"state");
  state = state_json->valueint;
  if(state == 1)
  {
   ssid_json = cJSON_GetObjectItem(root,"ssid");
   psw_json = cJSON_GetObjectItem(root,"psw");
  }
  else
  {
    type_json = cJSON_GetObjectItem(root,"type");
    mac_json = cJSON_GetObjectItem(root,"mac");
  }
  //对state进行jiexi
  switch(state){
  //当前连接状况查询
  case 2:  //接收到旗下设备
   os_printf("sss%d",state);
   os_timer_disarm(&Tcp_Connect_t);	
   Save_type[Save_Num] = type_json->valueint;
   Save_Mac[Save_Num] = mac_json->valuestring;
   Save_Num++;
   cJSON *Result = cJSON_CreateObject();
   cJSON_AddNumberToObject(Result,"state",3);
   cJSON_AddStringToObject(Result,"mac",StationMac_String);
   char *succeedData = cJSON_Print(Result);
   char data[1024];
   os_sprintf(data,"%s",succeedData);
   espconn_send((struct espconn*)arg,data,strlen(data));
       //wifiStationConnect(ssid,psw);
   TCP_Connect_Time_Init(4000);
      break;
  //开始连接AP
  case 1:
   if(ssid_json && psw_json){
   ssid = ssid_json->valuestring;
    psw  = psw_json->valuestring;
    Wifi_SSID = ssid;
    Wifi_PSW = psw;
    os_printf("SSID:%s",Wifi_SSID);
    os_printf("PSW:%s",Wifi_PSW);
   //构建JSON包,发送
    cJSON *Result = cJSON_CreateObject();
    cJSON_AddNumberToObject(Result,"status",2);
    cJSON_AddStringToObject(Result,"msg","AP Connect");
    char *succeedData = cJSON_Print(Result);
    char data[1024];
    os_sprintf(data,"%s",succeedData);
    espconn_send((struct espconn*)arg,data,strlen(data));
    //wifiStationConnect(ssid,psw);
   }else{
    os_printf("width null\n");
   }
  }
 }

实际上,switch判断里我们只用到状态1的情况,状态2只是我预留的而已。

接下来我们只需要在发送成功的回调函数里进行WiFi连接和等待连接上WIFI后进行UDP连接。

发送成功回调函数

espconn_disconnect(&User_Tcp_Espconn);  //断开TCP连接
  os_printf("SSID:%s,PSW:%s",Wifi_SSID,Wifi_PSW);
  wifiStationConnect(Wifi_SSID,Wifi_PSW);  //连接WIFI
  udp_client_init();  //UDP连接初始化
void ICACHE_FLASH_ATTR
wifiStationConnect(char *wifi_ssid,char *wifi_psw)
{
 struct station_config station_cfg;
 wifi_set_opmode(0x01);
 os_strcpy(station_cfg.ssid,wifi_ssid);
 os_strcpy(station_cfg.password,wifi_psw);
 wifi_station_set_config(&station_cfg);
 os_delay_us(100);
 wifi_station_connect();
 }
void Check_WifiState(void) {
static uint8 num = 0;
 uint8 getState = wifi_station_get_connect_status();
 //如果状态正确,证明已经连接
 if (getState == STATION_GOT_IP) {
 wifi_set_broadcast_if(0x01);  //设置 ESP8266 发送 UDP广播包时,从 station 接口发送
  user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));//分配空间
  user_udp_espconn.type = ESPCONN_UDP;      //设置类型为UDP协议
  user_udp_espconn.proto.udp->local_port = 2000;      //本地端口
  user_udp_espconn.proto.udp->remote_port = 8266;      //目标端口
  const char udp_remote_ip[4] = { 255, 255, 255, 255 };   //目标IP地址(广播)
  os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);
  espconn_regist_recvcb(&user_udp_espconn, User_Udp_Recv_Cb);    //接收
  espconn_regist_sentcb(&user_udp_espconn, User_Udp_Sent_Cb);    //发送
  espconn_create(&user_udp_espconn);      //建立 UDP 传输
  cJSON *Result = cJSON_CreateObject();
      cJSON_AddNumberToObject(Result,"status",2);
      cJSON_AddStringToObject(Result,"Tdevice",TargetDevice);
      cJSON_AddNumberToObject(Result,"type",type);
      cJSON_AddStringToObject(Result,"mac",StationMac_String);
      char *succeedData = cJSON_Print(Result);
      char data[1024];
      os_sprintf(data,"%s",succeedData);
      espconn_sent(&user_udp_espconn, data, strlen(data));
  }
  num++;
  if(num > 15)
  {
   num = 0;
   os_timer_disarm(&checkTimer_Wifistate);
   MQTT_Connect_Init();
  }
 }
 }

void udp_client_init() //初始化
{
os_timer_setfn(&checkTimer_Wifistate, (os_timer_func_t *) Check_WifiState,
 NULL);   //设置定时器回调函数
 os_timer_arm(&checkTimer_Wifistate, 500, 1);   //启动定时器,单位:毫秒
}

TCP连接断开后,我们要等确认模块已经连接上无线网络后再进行UDP连接,进行UDP连接前要确保UDP服务端已经开启了。

TCP接收处理和UDP连接着部分的程序我基本放上来了,大家伙可以直接复制过去,有哪里出错了可以联系我更改。

好了,前期的准备我们基本做完了,下一次我们就要通过MQTT连接阿里云物联平台了,尽请期待!