ESP8266http工作队列的实现方法

>   有一次在做开发的过程中,发现8266的三个任务已经尽数用完了o(╯□╰)o。没办法,串口驱动也要用一个呢。后来干脆想,把HTTP的任务加在队列里,定时扫描队列出对执行就好了,然后就开始构想代码。于是就是下面两片代码。

    app_net_work.c为上层提供app_net_work_init()、http_set_work(http_work_t job),这两个函数,顾名思义就是初始化队列和入队。

    然后app_http.c是再下一层,作用是描述具体任务,主要是将工作号和任务对应起来,这里用到了函数指针数组,这样可以方便自由地增删新的函数,不过注意在接收函数末了加入判断是否将GlobalHttp.info.isworking置0,以使该工作是否从队列中删除。
/*
 * app_net_work.h
 *
 *  Created on: 2017年5月25日
 *      Author: Administrator
 */

#ifndef APP_INCLUDE_APP_NET_WORK_H_
#define APP_INCLUDE_APP_NET_WORK_H_

#include "jobs_of_net_work.h"

#define HTTP_TASK_SIZE  8

ETSTimer net_work_timer;

typedef struct{
    http_work_t     task_sequence[HTTP_TASK_SIZE];
    struct {
        uint8_t         active:4;
        uint8_t         current:3;
        uint8_t         isworking:1;
    }info;
}http_task_t;

http_task_t GlobalHttp;

int ICACHE_FLASH_ATTR app_net_work_init();
int ICACHE_FLASH_ATTR http_set_work(http_work_t job);

#endif /* APP_INCLUDE_APP_NET_WORK_H_ */
/*
 * app_net_work.c
 *
 *  Created on: 2017年5月25日
 *      Author: Administrator
 */
#include "includes.h"
#include "client.h"
#include "app_net_work.h"
#include "app_http.h"


//把工作加入队列
int ICACHE_FLASH_ATTR http_set_work(http_work_t job){

    if ((GlobalHttp.info.current + 1) % HTTP_TASK_SIZE == GlobalHttp.info.active)
    {
        os_printf("\r\nIn queue error,may be full.\r\n");
        return FALSE;
    } //队满,无法添加
    GlobalHttp.task_sequence[GlobalHttp.info.current] = job;  //插入元素
    GlobalHttp.info.current =  (GlobalHttp.info.current + 1) % HTTP_TASK_SIZE; //队尾指针+1

    os_printf("\r\nIN queue:%d\r\n",job);
    return TRUE;

}

//定时扫描任务
int ICACHE_FLASH_ATTR ScanJobfn(){
    http_work_t HttpJob;
#ifdef HTTP_QUEUE
    os_printf("\r\nScan job.\r\n");
#endif
    if (GlobalHttp.info.active == GlobalHttp.info.current){
        GlobalHttp.info.isworking = 1;//避免非空队执行时候误删队首
#ifdef HTTP_QUEUE
        os_printf("\r\nempty\r\n");
#endif
        return FALSE; //队空,无法出队或执行
    }
    if(GlobalHttp.info.isworking == 0){//如果上一个任务完成
        GlobalHttp.info.active = (GlobalHttp.info.active + 1) % HTTP_TASK_SIZE;
#ifdef HTTP_QUEUE
        os_printf("  --%d-",GlobalHttp.info.active); //队头指针+1,删除队首
#endif
        if (GlobalHttp.info.active == GlobalHttp.info.current){
            GlobalHttp.info.isworking = 1;//避免非空队执行时候误删队首
#ifdef HTTP_QUEUE
            os_printf("\r\n. empty\r\n");
#endif
            return FALSE; //队空,无法执行
        }
    }
    HttpJob = GlobalHttp.task_sequence[GlobalHttp.info.active];//读取队首
#ifdef HTTP_QUEUE
    os_printf("%d %d\n",HttpJob,GlobalHttp.task_sequence[GlobalHttp.info.active+1]);
#endif
    if(true == startHttpWork(HttpJob))//如果执行不出错
        os_timer_disarm(&net_work_timer);//工作执行,暂停扫描
    GlobalHttp.info.isworking = 1;//去执行,故置一
    return TRUE;
}


int ICACHE_FLASH_ATTR app_net_work_init(){
    initHttpWork();
    GlobalHttp.info.isworking = 1;
    GlobalHttp.info.active = GlobalHttp.info.current = 0;       //队空
    os_timer_setfn(&net_work_timer,ScanJobfn,NULL);
    os_timer_arm (&net_work_timer,3000,1);
    return TRUE;
}
/*
 * app_http.h
 *
 *  Created on: 2017年5月25日
 *      Author: Administrator
 */

#ifndef APP_INCLUDE_APP_HTTP_H_
#define APP_INCLUDE_APP_HTTP_H_

#define POST "POST %s HTTP/1.1\r\nHOST: %s\r\nUser-Agent: wifi/1.0\r\nContent-Type:application/json;charset=UTF-8\r\nContent-Length: %d\r\n\r\n\r\n%s"


#include "hh_json.h"
#include "includes.h"
#include "app_net_work.h"
#include "client.h"
void ICACHE_FLASH_ATTR initHttpWork();
int ICACHE_FLASH_ATTR startHttpWork(http_work_t job_flag);




#endif /* APP_INCLUDE_APP_HTTP_H_ */
/*
 * app_http.c
 *
 *  Created on: 2017年5月25日
 *      Author: Administrator
 */
#include "app_http.h"
#include "hh_json.h"
#include "user_main.h"
#include "string.h"
#include "driver/mqtt.h"
#include "user_mqtt.h"

extern http_task_t GlobalHttp;
ETSTimer wait_wifi_conn;

void ICACHE_FLASH_ATTR NULL_fn(){}
/*****************************************************/
/********************自定义接收函数**********************/

void ICACHE_FLASH_ATTR regist_recv_cb(void *arg,char *pdata,unsigned short len){
os_printf("\nregist_recv_cb:%s\n",pdata);
/*略*/
if(success) GlobalHttp.info.isworking = 0;//略写部分具有判断是否执行isworking=0的机制,可以理解成略去部分已经进行了对success变量进行处置。
}

void ICACHE_FLASH_ATTR login_recv_cb(void *arg,char *pdata,unsigned short len){
os_printf("\nlogin_recv_cb\n");
/*略*/
if(success) GlobalHttp.info.isworking = 0;
}

void ICACHE_FLASH_ATTR module_ota_recv_cb(void *arg,char *pdata,unsigned short len){
    /*略*/
    if(success) GlobalHttp.info.isworking = 0;
}

void ICACHE_FLASH_ATTR module_ota_download_cb(void *arg,char *pdata,unsigned short len){
    /*略*/
    if(success) GlobalHttp.info.isworking = 0;
}

//回调函数的数组
void* user_tcp_recv_cb[HTTP_TASK_SIZE]={NULL_fn,regist_recv_cb,login_recv_cb,NULL_fn,module_ota_recv_cb,module_ota_download_cb};
/********************自定义接收函数***********************/
/*****************************************************/



/**********************自定义组包函数**********************/
/*****************************************************/

void ICACHE_FLASH_ATTR regist_recv_pack(char* buf){
    /*略*/
}

void ICACHE_FLASH_ATTR login_recv_pack(char* buf){
    /*略*/
}

void ICACHE_FLASH_ATTR module_ota_pack(char* buf){
    /*略*/

}

void ICACHE_FLASH_ATTR module_ota_download_pack(char* buf){
    /*略*/
}

void (*user_make_package[HTTP_TASK_SIZE])(char*)={NULL_fn,regist_recv_pack,login_recv_pack,NULL_fn,module_ota_pack,module_ota_download_pack};
/**********************自定义组包函数*************************/
/*********************************************************/





int ICACHE_FLASH_ATTR startHttpWork(http_work_t job_flag)
{
    os_printf("\r\nHTTP JOB: %d\r\n",job_flag);
    //需要发的东西打包的函数
    (user_make_package[job_flag])(sent_buffer);
    os_printf("\r\n%s\r\n",sent_buffer);
    if(0 != espconn_connect(&user_tcp_conn[job_flag])) {
        os_printf("\nFAIL TO start CONNECT\n");
        return false;
    }
    espconn_regist_recvcb(&user_tcp_conn[job_flag],user_tcp_recv_cb[job_flag]);
    return true;
}

void ICACHE_FLASH_ATTR DSNfound(const char *name, ip_addr_t *ipaddr, void *arg){
    struct ip_info ipinfo;
    os_printf("{\r\n-------------------\r\n}");
    wifi_get_ip_info(STATION_IF,&ipinfo);
    os_printf("{\r\n-------------------\r\n}");
    char textip[4]={192,168,1,209};        //测试使用ip地址
    my_tcp_station_init((struct ip_addr*)textip,&ipinfo.ip,10025);//创建链接
    //my_tcp_station_init(ipaddr,&ipinfo.ip,80);
    os_printf("{\r\n-------------------\r\n}");
    os_timer_disarm(&wait_wifi_conn);
    //wifiConnectCb(wifi_station_get_connect_status());
}




void ICACHE_FLASH_ATTR startinit(){
    ip_addr_t dns_addr;//这个接口函数要,没用但是要定义
    struct espconn user_con;
    if(wifi_station_get_connect_status() != STATION_GOT_IP) return;
    if(ESPCONN_OK == espconn_gethostbyname(&user_con,MY_COMPANY_DNS, &dns_addr,DSNfound))
        os_timer_disarm(&wait_wifi_conn);
}

void ICACHE_FLASH_ATTR initHttpWork(){
    os_timer_setfn(&wait_wifi_conn,startinit,NULL);
    os_timer_arm(&wait_wifi_conn,2000,1);
    os_printf("-");
}

你可能感兴趣的:(ESP8266http工作队列的实现方法)