基于ESP8266 SDK部分功能的二次封装

时间:2023-02-01 22:21:38

一,目的。

使用ESP8266官方提供的固件SDK的人都知道,在大部分的API接口调用和使用逻辑上跟标准C APP开发是有很大差别的,有些功能需要自己花很大时间去进行功能封装和逻辑设计,对于一个精通C语言的人,也很难在短时间内开发出一个简单功能的。同时如果需要使用硬件驱动功能,如:I2C,UART,PWM等,没有驱动开发经验的人即使把代码写出来了,但一旦遇到问题,也很难去解决,这需要有一定的硬件知识和驱动调试经验。为此,我在平时的工作中花了一些时间对一具非通用性的API函数接口、单元功能逻辑和硬件驱动相关的进行了封装,通过这套接口,对于一个只会C应用开发的人来说,能很快地理解和使用基本硬件功能。


二,编译环境和基本要求

搭建ESP8266的编译环境,请参考:http://blog.csdn.net/yunjinwang/article/details/52668330

ESP8266SDK分NONOS和RTOS两种,我这里是针对NONOS的,有一定的C语言基础即可,懂一点硬件知识和驱动知识更佳,会简单的shell命令和makefile知识。

有linux基础的建议搭建Linux编译环境,稳定可靠效率高。


三,封装SDK的下载

由于在工作中会有一具的功能优化、bug fix和功能增加,如有疑问请发邮件:wyj0617mail@aliyun.com


考虑到更新和便捷性,将最新SDK及测试代码放在svn服务器上。http://www.smartinhome.cn:8001/svn/espSdkRelease,用户名:user, 密码:user

最新的SDK接口函数与下面的描述有异,请以最新的SDK头文件描述为主。


20170220已更新支持安信可的ESP8266IDE环境,测试通过,SDK中有方法说明。


四,API函数接口功能及介绍

a,auto_sys_utils.h  系统基本功能模块

1, void AIH_log_init();初始化串口log输出,波特率固定为115200, 8N1

2, int8_t AIH_key_init(int8_t *gpioNumArray,  int8_t arrayNum, key_press_cb keyCb);初始化GPIO输入,目前支持GPIO 0\2\4\5\12\13\14\15,GPIO口初始化后会拉高,当检测到低电平时,触发PRESS,key_press_cb回调函数后返回按键事件的类型及长短按,3秒算长按

3,int8_t AIH_status_light_set(int8_t gpioNum, int8_t defaultStatus, int32_t intralMs);设置某一GPIO口按设置的intralMs闪烁,目前支持GPIO 0\2\4\5\12\13\14\15\16

4,int8_t AIH_gpio_output(int8_t gpioNum,  int8_t level);和int8_t AIH_gpio_input(int8_t gpioNum);用来输入某一GPIO口的高低电平和从某一GPIO口读取当前电平值;

5,int32_t AIH_wifi_mode_switch(int8_t mode, AIH_WIFI_INFO_S *wifiInfo, wifi_evt_func_cb evtfuncCb, void *userData);用来设置当前WIFI的类型(0---STA/1---AP)及获取WIFI的结果及属性值,从回调函数wifi_evt_func_cb中返回;

6,void AIH_property_erase_sector(uint32_t sectorAddr);擦除某一扇区的数据,这里是以扇区的地址开始的4096个字节被擦除;

7,int32_t AIH_property_set(int8_t *inData, uint32_t size, uint32_t startAddr);和int32_t AIH_property_get(int8_t *outData, uint32_t size, uint32_t startAddr);是用来设置和获取存储的数据,对存储区的开始地址必须是以一个扇区为单位,存储数据长度以4字节为最小单位;

8,void AIH_get_ntp_time(get_ntp_cb cb);获取当前的NTP时间,需要先配置能上外网,NTP时间从回调函数get_ntp_cb返回;

9,int32_t AIH_sw_timer_register_func(uint32_t delayMs, AIH_SW_TIMER_CB funcCb, void* cookie);注册定时器函数;

10,int32_t AIH_sw_timer_remove_func(int32_t timerId); 从系统中移出已注册的定时器函数;

9,char *AIH_get_version();获取当前SDK的版本信息。


b,auto_wifi_config.h wifi配置及局域网发现模块

1, int32_t AIH_wifi_config_start(int32_t broadcastPort, wifi_config_func apConfCb);负责切换到AP模式并监听broadcastPort端口的UDP广播包,手机端发送的UDP包内容格式如:{"SSID":"XXXXXXX","PWD":"XXXXXX","RETPORT":2345},其中RETPORT是手机端监听的UDP端口,配置成功后设备会发送“success”到手机,告之配置成功。手机端需要自己实现;

2,void AIH_wifi_config_stop();停止AP配置模式;

3,int32_t AIH_ak_config_start(char *aesKey, wifi_config_func confCb);负责将WIFI切换到混杂模式监听路由配置信息,支持微信的airkiss和ESP的ESPTouch两种。aesKey是加密密钥,默认为NULL,手机客户端需要集成微信IOT官网和ESP提供的相关SDK。

4,void AIH_ak_config_stop();停止配置模式;

5,int8_t AIH_ak_lan_discover_start(void);启动支持微信局域网发现服务;

6,void AIH_ak_lan_discover_stop(void);停止微信局域网发现服务;


c,auto_socket_utils.h TCP/UDP socket相关模块

1,int32_t get_addr_by_host(char *hostName, get_host_cb_t cb);根据域名解析IP地址,需要连接外网;

2,int32_t udp_server_create(int32_t localPort, espconn_recv_callback cbFunc);创建一个UDP server对象,监听localPort, 收到信息后在cbFunc中获取;

3,void udp_server_delete(int32_t udpSvrHandle);停止一个UDP server并销毁这个r对象;在这个server无用时,一定要调用这个函数,否则容易造成内在泄漏;

4,int32_t udp_send_msg(uint8_t *dstIp, int32_t dstPort, uint8 *psent, uint16 length);发送特定长度length的UDP包psent到指定的IPdstIp和端口dstPort;


5,TCPHANDLE tcp_server_create(int32_t lisPort);创建一个TCP服务,监听端口lisPort;

6,int32_t tcp_server_start(TCPHANDLE tcpHandle, tcp_listen_cb_t evt_cb, void *userdata);开启已经创建的TCP服务,设置端口监听新连接的回调函数evt_cb;

7,int32_t tcp_server_set_sub_connection_cb(TCPHANDLE tcpHandle, int32_t subTcpIndex, tcp_event_cb evt_cb, void *userdata);当收到一个客户端连接后,为这个连接设置事件回调函数;
8,int32_t tcp_server_sub_send_msg(TCPHANDLE tcpHandle, int32_t subTcpIndex, uint8 *sndData, uint16 length);使用创建的连接给远程客户端发送消息
9,int32_t tcp_server_sub_disconnect_client(TCPHANDLE tcpHandle, int32_t subTcpIndex);断开某一个指定的连接;
10,int32_t tcp_server_delete(TCPHANDLE *pTcpHandle);停止server并销毁;


11,int32_t tcp_client_create(int8_t isChkMsg);创建一个TCP客户端,isChkMsg是用来标识是否需要在消息的前后增加"<<"和">>"来标识TCP流的起止点,需要服务端同步配合;

11-1,int32_t tcp_client_create_ssl(int8_t isChkMsg);创建一个TCP客户端,使用SSL加密传输,需要服务器支持,isChkMsg是用来标识是否需要在消息的前后增加"<<"和">>"来标识TCP流的起止点;
12,int32_t tcp_client_connect_svr(int32_t tcpHandle, uint8_t *svrIp, int32_t svrPort, tcp_event_cb evt_cb, void *userdata);连接指定IP和PORT的TCP server,并设置事件回调函数;
13,int32_t tcp_client_send_msg(int32_t tcpHandle, uint8 *sndData, uint16 length);发送指定长度的消息到已连接的服务端;
14,int32_t tcp_client_disconnect_svr(int32_t tcpHandle);断开与服务端的连接;
15,int32_t tcp_client_delete(int32_t tcpHandle);销毁TCP客户端对象;


d,auto_json_utils.h JSON解析模块,目前仅支持一级JSON

1,int32_t AIH_json_init(char *jsonStr, int32_t len); 使用已有的JSON数据及长度创建JSON解析器对象;
2, void AIH_json_deinit(int32_t jsonHandle); 销毁已有的JSON解析器对象;
3, int32_t AIH_json_get_pair_num(int32_t jsonHandle);获取已创建的解析器有多少个对象;
4, int32_t AIH_json_get_keyword(int32_t jsonHandle, int32_t id, char *outKeyWord, int32_t maxLen);根据索引ID获取关键字内容
5, int32_t AIH_json_get_id_by_keyword(int32_t jsonHandle, char *inKeyWord);获取指定关键字对象的位置索引ID;
6, int32_t AIH_json_get_type(int32_t jsonHandle, int32_t id);获取指定索引ID值的类型,//0----number, 1----string
7, int32_t AIH_json_get_int_value(int32_t jsonHandle, int32_t id);如果ID位置的内容是整形,获取对象整数值
8, int32_t AIH_json_get_string_value(int32_t jsonHandle, int32_t id, char *outValue, int32_t maxLen);如果ID位置的内容是字符串,获取字符串内容


e, auto_pwm_utils.h 设置PWM操作模块

1, void AIH_pwm_init(uint16 freq, uint32 (*pin_info_list)[3], uint32 pwm_channel_num);初始化硬件PWM相关GPIO口,freq不能大于2000,pin_info_list[][3]={{PERIPHS_IO_MUX_MTMS_U, 14, FUNC_GPIO14},...}, pwm_channel_num表示pin_info_list长度
2, void AIH_pwm_start(void);开始使用所有GPIO口的PWM功能
3, void AIH_pwm_set_duty(uint8 duty, uint8 channel);设置某一特别通道0<=channel<pwm_channel_num的占空比,0<= duty<=100
4, uint8 AIH_pwm_get_duty(uint8 channel);获取某一PWM通道的占空比;
5, void AIH_pwm_set_freq(uint16 freq);设置设备的PWM频率;

6, uint16 AIH_pwm_get_freq(void);获取设备当前的PWM频率;


f, auto_i2c_master.h I2C操控模块

1, int32_t AIH_i2c_master_gpio_init(int8_t sdaGpioNum, int8_t sclGpioNum); 指定SDA和SCL对应的GPIO口进行I2C初始化
2, void AIH_i2c_master_start(void); 在执行一次操作命令前需要先start
3, void AIH_i2c_master_stop(void);在执行完一次操作后需要stop
4, void AIH_i2c_master_setAck(uint8 level);写入一个ACK
5, uint8 AIH_i2c_master_getAck(void); 读取一个ACK
6, uint8 AIH_i2c_master_readByte(void); 读取一个字节的数据
7, void AIH_i2c_master_writeByte(uint8 wrdata);写一个字节的数据

对于I2C这样的操作接口,关键在于多用,熟悉各函数的调用顺序,以下是一个简单的写操作的封装,可供参考:
/*eg:
LOCAL bool ICACHE_FLASH_ATTR
test_i2c_write(uint8 addr, uint8 *pData, uint16 len)
{
    uint8 ack;
    uint16 i;


    auto_i2c_master_start();
    auto_i2c_master_writeByte(addr);
    ack = auto_i2c_master_getAck();


    if (ack) {
        os_printf("addr[0x%x] not ack when tx write cmd\n", addr);
        auto_i2c_master_stop();
        return false;
    }


    for (i = 0; i < len; i++) {
        auto_i2c_master_writeByte(pData[i]);


        ack = auto_i2c_master_getAck();
        if (ack) {
            os_printf("data[0x%x] not ack when tx write cmd\n", pData[i]);
            auto_i2c_master_stop();
            return false;
        }
    }
    auto_i2c_master_stop();
    
    return true;
}
*/


g,  auto_msgd_engine_client.h  这是为了实现一个消息推送功能而写的,需要配合server端和client端共同使用[我单独整理一个关于msgd消息推送相关的BLOG,目前已支持ESP8266、LINUX、WINDOW、IOS、ANDROID各通用平台,详情请参阅:http://blog.csdn.net/yunjinwang/article/details/54602534]

1,int32_t esp_msgd_client_init(ESPMSGDCLIHandle *handle, ESP_MSGD_CLIENT_TYPE_E cliType, uint8 *remoteHostIp, int remoteHostPort);;初始化客户端对象,并连接指定MSGD服务端IP和PORT;

2,int32_t esp_msgd_client_register_topic(ESPMSGDCLIHandle handle, char *groupName, char *userName);设置客户端所属于的GROUP和USER ID,用于到MSGD服务端注册;

3,int32_t esp_msgd_client_set_keepalive(ESPMSGDCLIHandle handle, int32_t interntimeSec, char *aliveMsg, int32_t aliveMsgLen);设置KEEPALIVE参数,用于保持TCP的长连接状态;

4,int32_t esp_msgd_client_set_listener(ESPMSGDCLIHandle handle, ESP_MSGD_CLIENT_FUNC_EVT_CB evtCb, ESP_MSGD_CLIENT_FUNC_MSG_CB msgCb, void *userData);设置事件回调函数和接收推送消息的回调函数

5,int32_t esp_msgd_client_start(ESPMSGDCLIHandle handle, char *encrypt);开始接收消息推送,使用加密密钥encrypt来传输安全数据;

6,int32_t esp_msgd_client_send_p2p_msg(ESPMSGDCLIHandle handle, char *dstGroup, char *dstUser, int32_t persistTime, char *msg, int32_t msgLen, int32_t msgId);根据注册的类型可P2P发送消息;

7,int32_t esp_msgd_client_publish_msg(ESPMSGDCLIHandle handle, char *dstGroup, int32_t persistTime, char *msg, int32_t msgLen, int32_t msgId);根据注册的类型可推送消息;

8,int32_t esp_msgd_client_stop(ESPMSGDCLIHandle handle);停止接收消息推送并断开与服务端的连接;

9,int32_t esp_msgd_client_uninit(ESPMSGDCLIHandle *handle);停止相关功能及销毁对象;