简介

U-SDK为软件中间件,提供了点对点消息、发布订阅主题消息、群消息、文件传输、内网直连等功能,本开发向导帮助用户 在ESP8266平台上实现点对点消息功能。 开发向导以小e为例。

 


环境准备

 


接口基础

  • USDK通过实现移植接口可适配不同的MCU平台,并且各项功能可进行裁剪配置,我们已事先按照常规需求编译了多个不同功能的库, 用户下载的SDK包中,库文件压缩包包含了多个子目录,其命名规则如下:
    • RTOS表示在RTOS环境下使用;
    • iLink表示启用IM外网功能;
    • local表示启用内网直连功能;
    • file表示启用文件功能;
    • log表示启用了日志打印;
  • 本例中我们使用的库为ESP8266平台库: RTOS_iLink_local_file_log.a
  • USDK的参考开发过程如下:
    USDK开发流程

 


ESP8266基础

 

1. 程序入口

ESP8266采用FreeRTOS,应用程序入口函数为void user_init(void), 用户的应用程序应从入口函数中初始化,包括硬件初始化、网络初始化、定时器初始化等操作。


void user_init(void)
{
    os_printf("now SDK version:%s\n";, system_get_sdk_version());
    // show logo
    user_show_logo();
}
            

 

2. WiFi设置

  • WiFi模式

    • ESP8266的WiFi具备AP、Station、AP+Station模式,若只需要通过ESP8266连接路由器则只需采用Station模式, 在此我们采用Station模式,开发板连接路由器实现互联网连接,进而与其他平台的通信。设置模式:

      
      wifi_set_opmode(STATION_MODE);
                  
    • 本设置若与原设置不同,将会保存到flash系统参数区并立即生效。
  • WiFi配置参数

    • 在Station模式下,需要对应的AP(在此即为无线路由)信息,因我们将采用Smartconfig来配置AP参数,配置后将 参数将存储到flash参数配置区,硬件在初始化时会自动将读取flash内存储的配置参数进行连接。在此我们仅读取参数供查看:

        
      struct station_config config;
      if(wifi_station_get_config_default(&config) == true)
      {
          os_printf("SSID:%s \n",config.ssid);
          os_printf("AP_MAC:"MACSTR"\n", MAC2STR(config.bssid));
      }
                  
  • SmartConfig

    • 首先我们实现并创建一个airkiss_key_poll_task任务,该任务用于检测开发板上配置按键状态, 当该按键按下一段时间我们则任务需要进行WiFi配置,开始启动smartconfig:

      
      xTaskCreate(airkiss_key_poll_task, "smartconfig_task", 256, NULL, 2, NULL);
                  
    • airkiss_key_poll_task任务中,若判断开始进行WiFi配置,首先启动Smartconfig并设置其回调函数 ,设置状态灯闪烁:

       
      smartconfig_start(smartconfig_done);
      user_set_wifi_led_delay(500);
                  
    • 在smartconfig过程中通过smartconfig_done回调中处理各连接状态:

      • SC_STATUS_FIND_CHANNEL:可以使用微信开始进行WiFi配置
      • SC_STATUS_LINK:可将WiFi配置参数写入flash,并手动连接,下次模块启动时将使用flash内存储的参数连接

        
        wifi_station_set_config(sta_conf);
        wifi_station_disconnect();
        wifi_station_connect();
                    
      • SC_STATUS_GETTING_SSID_PSWD:获取到SSID及密码
      • SC_STATUS_LINK_OVER:成功获取到IP地址,连接路由完成,停止smartconfig

        
        user_set_wifi_led_on();
        smartconfig_stop();
                    
    • 开启Smartconfig后可通过微信 “开发快公众号->我的设备->配置绑定” 来配置模块的wifi参数

      使用smartconfig时需注意以下事项:

      • 在单station模式下可使用smartconfig进行WiFi配置;
      • smartconfig_start未完成前不可重复执行smartconfig_start
      • smartconfig 过程中,ESP8266 station 和 soft-AP 失效
      • 注意处理密码错误等异常状态
  • WiFi事件回调

    • 通过设置WiFi状态回调可针对不同的WiFi状态进行用户处理,因模块默认会自动重连,在此我们需特别注意区分 Smartconfig失败与其他断连状态

      
      wifi_set_event_handler_cb(et_wifi_event_cb);
                  
    • 区分处理Smartconfig过程产生的断连、开机无法连接网络、网络异常导致连接中断这几种情况

      • 当Smartconfig过程产生的断连我们需要正常运行程序,使用户可以更改WiFi参数
      • 开机无法连接网络仍正常运行程序,等待WiFi连接
      • 网络异常导致正常连接中断,重启模块
      
      // user_init入口内初始化
      wifi_reconnect_start_flag = 0;
                  
      
      // airkiss_key_poll_task任务启动smartconfig标志
      wifi_reconnect_start_flag = 0;
                  
      
      //smartconfig_done回调SC_STATUS_LINK状态
      wifi_reconnect_start_flag = 3;
                  
      
      // wifi_reconnect_start_flag传递入et_user_main任务,获取到IP之后
      et_int32 *p_wifi_reconnect_start_flag = (et_int32 *)pvParameters; 
      *p_wifi_reconnect_start_flag = 1;
                  
      
      //WiFi事件回调
      void et_wifi_event_cb(System_Event_t *event)
      {
          //…
          case EVENT_STAMODE_DISCONNECTED:    //WiFi断连事件
              user_set_wifi_led_off();//熄灭状态灯
              if(wifi_reconnect_start_flag != 1)//WiFi未成功连接过
              {
                  if(wifi_reconnect_start_flag == 3)//Smartconfig失败
                  {
                      smartconfig_stop();//停止Smartconfig
                  }
              }
              else//WiFi成功连接后出现断连
              {
                  system_restart();//重启系统
              }
              break;
          //…
      }
                  
  • WiFi状态灯

    • 用户可通过MCU SDK的接口配置WiFi状态灯

      
      wifi_status_led_install(WIFI_STATUS_IO_NUM, WIFI_STATUS_IO_MUX, WIFI_STATUS_IO_FUNC);
                  
    • 但该接口无法指示smartconfig状态,在此我们使用ET-iLink提供的 wifi_led.c中提供的接口创建任务来进行WiFi状态指示,并在WiFi事件回调中指示状态

      
      xTaskCreate(user_wifi_led_control, "wifi_led_control", 256, NULL, 2, NULL);
                  
  • 用户任务

    • 可以进行WiFi配置与连接后,需要创建用户任务处理进行ET-iLink连接以及数据处理:

      
      xTaskCreate(et_user_main, "et_user_main", 512, (void *)&wifi_reconnect_start_flag, 5, NULL);
                  
    • 在用户任务et_user_main中我们判断WiFi是否成功连接,若成功连接则开启ET-iLink服务,通过 wifi_station_get_connect_status我们可以获取WiFi状态,若状态为STATION_GOT_IP则已从AP获取到IP, 可以开始数据通信,否则等待WiFi连接成功

      
      et_int32 *p_wifi_reconnect_start_flag = (et_int32 *)pvParameters;
      while(1 != *p_wifi_reconnect_start_flag)
      {
          wifi_get_ip_info(STATION_IF, &ipconfig);
          if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0) 
          {
              os_printf("Wifi connect success, got ip !!! \r\n");
              *p_wifi_reconnect_start_flag = 1;//连接成功
          }
          else 
          { 
              //等待连接
              vTaskDelay(1000/portTICK_RATE_MS);
          }
      }
                  

 


U-SDK移植

 


消息收发

 

1. 创建上下文

  • 在已知UID、AppKey、SecretKey的情况下可创建一个ET-iLink上下文,USDK不支持多实例。

#define UID “1234567890abcdefghjklmnopqrstuvwxy”        //此处仅作为示例
#define APPKEY “01234567-8901-234567”                   //此处仅作为示例
#define SECRETKEY “01234567890123456789012345678901”    //此处仅作为示例
#define SERVER "lb.kaifakuai.com"
#define PORT 8085

et_cloud_handle g_cloud_handle = NULL;
et_net_addr_type g_lb_addr;

g_lb_addr.name_ip = SERVER;
g_lb_addr.port = PORT;
g_cloud_handle = et_create_context(UID, APPKEY, SECRETKEY, g_lb_addr);
            

 

2. 设置回调

  • 创建实例后,用户需要实现消息回调及事件回调,通过回调接口处理SDK消息及事件,用户应在创建USDK处理任务前设置回调

//实现回调接口
void et_message_process(et_int32 type, et_char *send_userid, et_char *topic_name, et_int32 topic_len, et_context_mes_type *message)
{
    //此处省略了消息处理代码
}
void et_event_process(et_event_type event)
{
    //此处省略了事件处理代码
}
//设置回调
et_set_callback(g_cloud_handle,et_message_process, et_event_process);
            

 

3. 创建SDK处理任务

  • 创建SDK处理任务

注意任务堆栈空间请依据实际需要设置,并合理设置任务优先级


//外网处理任务实现
void et_ilink_task(void *pvParameters)
{
    et_int32 i_ilink_code;
    et_uint32 i_count = 0; 
    while(1)
    {
        i_count++;
        i_ilink_code = et_ilink_loop(pvParameters);
        taskYIELD();
    }
}

//创建任务
#if ET_CONFIG_CLOUD_EN    
to_stop_ilink = 0;
//任务栈设置为512,优先级为7
if(pdPASS == xTaskCreate(et_ilink_task, "iLink task", 512, g_cloud_handle, 7, NULL))
{
    ET_LOG_USER("============================\nCreate iLink task success\n============================\n");
}
else
{
    to_stop_ilink = 1;
    ET_LOG_USER("****************************\nCreate iLink task failed\n****************************\n");
}
#endif
            

 

4. 连接服务器

  • ET-iLink实例创建成功后,将得到一个句柄,使用该句柄用户可连接ET-iLink,用户连接前应先调用et_discover_servers() 发现一个最优的服务器,然后再调用et_connect()进行连接

et_cloud_connect_type g_cloud_con_para = {ET_TRUE, 90};//清除离线消息,心跳10s
et_discover_type g_discover = ET_DISCOVER_T_INITIAL;//初始化服务器发现数据结构

//因WiFi连接成功后外网可能短时间内仍无法访问,在此连接失败则重连5次
do
{
    rc = et_discover_servers(g_cloud_handle, &g_discover, 3000);//发现服务器
    if(rc != 0)
    {
        ET_LOG_USER("Discover iLink failed %d\n", num);
    }
    else
    {
        rc = et_connect(g_cloud_handle, &g_cloud_con_para, &g_discover, 3000);//连接服务器
        if(rc != 0)
        {
            ET_LOG_USER("Connect iLink failed %d\n", num);
        }
    }
    num++;
    vTaskDelay(num*100*portTICK_RATE_MS);
}while(rc != 0 && num < 5 && to_stop_app == 0);
            
  • 通过接口返回值判断连接是否成功;连接成功后断开将触发EVENT_CLOUD_DISCONNECT事件, 用户必须在此事件中进行重连;我们向et_event_process()回调中增加下列代码:

case EVENT_CLOUD_DISCONNECT://外网连接断开
    ET_LOG_USER("You are disconnect:0x%x\n", event.event_no, event.data);
    rc = et_reconnect(g_cloud_handle, 3000);
    if(rc<0)
    {
        ET_LOG_USER("Reconnect failed, sleep a moment\n");
        et_sleep_ms(2000);
    }
    g_reconnect_num++;
    ET_LOG_USER("Manual relogin %d\n", g_reconnect_num);
    break;
            

 

5. 点对点消息收发

  • 发送消息

    • 连接成功后用户可调用et_chat_to()接口进行点对点消息收发,所有消息接口将通过网络移植接口发送, 用户通过接口返回值判断是否发送成功数据,当接收到消息的服务器确认应答时将触发事件EVENT_CLOUD_SEND_SUCCESS

      
      #define RECIVER     "abcdefghjklmnopqrstuvwxy1234567890"
      #define MESSAGE     "Hello world,Hello iLink"
      //发送点对点消息
      i_ret_value = et_chat_to(g_cloud_handle, MESSAGE, et_strlen(MESSAGE), RECIVER);
      if(i_ret_value < 0)
      {
          ET_LOG_USER("Chat to failed %d", i_ret_value);
      }
                  
    • 向事件回调中添加如下代码

      
      case EVENT_CLOUD_SEND_SUCCESS://仅表示接收到服务器确认应答
          ET_LOG_USER("Cloud send success %d\n", event.data);
          et_loop_test.send_num++;
          break;
                  
  • 接收消息

    • 有其他用户向本机发送消息时,将在消息回调et_message_process()中得到通知,我们向消息回调中添加如下代码

      
      case MES_CHAT_TO_CHAT:
          ET_LOG_USER("Receive a Chat to chat message from %s\n", send_userid);
          et_loop_test.recv_num++;
          break;
                  

 

6. 断开服务器连接


i_ret_value = et_disconnect (g_cloud_handle);
            

 

7. 销毁上下文


et_destroy_context(&g_cloud_handle);
            

 


完整示例

开发示例