esp8266的TCP 学习
发现esp8266处理大多都是回调函数,总感觉没有主函数,有点很不习惯,要弄啥循环调用的,大部分都是用软件定时器,搞起来就像一个操作系统,只是任务创建好了给我们,我们看不到,(学了几天之后我体验到的,实际是不是这样的,后续我在更正)
首先需要先连接WiFi
void ICACHE_FLASH_ATTR
wifi_connect(char *ssid,char *password)//连接wifi
{
struct station_config stationConf;
wifi_set_opmode(STATION_MODE); //设置为STATION模式
os_strcpy(stationConf.ssid, ssid); //改成你自己的 路由器的用户名
os_strcpy(stationConf.password, password); //改成你自己的 路由器的密码
//wifi_station_get_config_default(&stationConf); //读出保存在flash 里面的数据
wifi_station_set_config(&stationConf); //设置WiFi station接口配置,并保存到 flash
os_printf("ssid:%s\r\n",stationConf.ssid);
os_printf("password:%s\r\n",stationConf.password);
}
我现在用的是定时器,来判断联网成功,因为函数里面不能有死等,有看门口复位
时间到了就检测一次
void ICACHE_FLASH_ATTR
user_init(void)//主函数里面
{
uart_init(57600, 57600);//设置串口0和串口1的波特率
wifi_connect("TKT OFFICE","taikwan@2017");
os_timer_disarm(&WITI_TIME); //取消定时器定时
os_timer_setfn(&WITI_TIME, (os_timer_func_t *) Check_WifiState,
NULL); //设置定时器回调函数
os_timer_arm(&WITI_TIME, 1000, true); //启动定时器,单位:毫秒500
}
tcp client
void Check_WifiState(void) {
uint8 getState;
getState = wifi_station_get_connect_status();
if (getState == STATION_GOT_IP) {
os_printf("WIFI连接成功!");
os_timer_disarm(&WITI_TIME); //取消定时器定时
if (getState == STATION_GOT_IP) {//真的连上的wifi
uart0_sendStr("WIFI连接成功!");//WIFI链接成功
// user_tcp_conn.proto.tcp->local_ip
//
// espconn_connect(&user_tcp_conn);
//
const char remote_ip[4] = { 192, 168, 1, 131};//目标IP地址,必须要先从手机获取,否则连接失败.
tcp_client((struct ip_addr *) remote_ip,8080);
return;
}
}
else
{//这里可以加上,连接失败重新链接,不过我们之后肯定不会把wifi写死的
}
}
//应该这些回调函数用不上就可以不注册
void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg) //发送
{
os_printf("Sending data succeeded!");
}
void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg) //断开
{
os_printf("Disconnect successful!");
}
void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg, //接收成功回调函数
char *pdata, unsigned short len) {
os_printf("Data received:%s\r\n", pdata);
espconn_sent((struct espconn *) arg, "0", strlen("0"));
}
void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
os_printf("Connection error, error code is%d\r\n", err);
espconn_connect((struct espconn *) arg);//重新链接
}
//注册成功就可以注册接受发送,断开的回调函数了,,,形参其实就是句柄
void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg) //注册 TCP 连接成功建立后的回调函数
{
struct espconn *pespconn = arg;
espconn_regist_recvcb(pespconn, user_tcp_recv_cb); //接收
espconn_regist_sentcb(pespconn, user_tcp_sent_cb); //发送
espconn_regist_disconcb(pespconn, user_tcp_discon_cb); //断开
espconn_sent(pespconn, "8226", strlen("8226"));//发送消息, 可以放到任意的地方,反正只是发送消息
}
//连接tcp server
void tcp_client(struct ip_addr *remote_ip,int remote_port)
{
struct ip_info info;
user_tcp_conn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空间
user_tcp_conn.type = ESPCONN_TCP; //设置类型为TCP协议
wifi_get_ip_info(STATION_IF, &info); //查询 WiFi模块的 IP 地址
os_memcpy(user_tcp_conn.proto.tcp->local_ip, &info, 4);//设置本地ip
os_memcpy(user_tcp_conn.proto.tcp->remote_ip, remote_ip, 4);//设置对方ip
user_tcp_conn.proto.tcp->local_port = espconn_port(); //本地端口
user_tcp_conn.proto.tcp->remote_port = remote_port; //目标端口
espconn_regist_connectcb(&user_tcp_conn, user_tcp_connect_cb);//注册 TCP 连接成功建立后的回调函数
espconn_regist_reconcb(&user_tcp_conn, user_tcp_recon_cb);//注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
if(ESPCONN_ISCONN==espconn_connect(&user_tcp_conn))
{
os_printf("tcp Connection successful\r\n");
}
}
ESP8266做服务器
espconn
typedef void* espconn_handle;
typedef struct _esp_tcp {
int remote_port;//对方的端口号
int local_port;//本地端口号
uint8 local_ip[4];//本机ip
uint8 remote_ip[4];//要连接的ip
espconn_connect_callback connect_callback;//连接成功回调函数
espconn_reconnect_callback reconnect_callback;//异常断开
espconn_connect_callback disconnect_callback;//断开连接
espconn_connect_callback write_finish_fn;
} esp_tcp;
typedef struct _esp_udp {
int remote_port;
int local_port;
uint8 local_ip[4];
uint8 remote_ip[4];
} esp_udp;
/** Protocol family and type of the espconn */
enum espconn_type {
ESPCONN_INVALID = 0,
/* ESPCONN_TCP Group */
ESPCONN_TCP = 0x10,
/* ESPCONN_UDP Group */
ESPCONN_UDP = 0x20,
};
enum espconn_option{
ESPCONN_START = 0x00,
ESPCONN_REUSEADDR = 0x01,
ESPCONN_NODELAY = 0x02,
ESPCONN_COPY = 0x04,
ESPCONN_KEEPALIVE = 0x08,
ESPCONN_MANUALRECV = 0x10,
ESPCONN_END
}
enum espconn_level{
ESPCONN_KEEPIDLE,
ESPCONN_KEEPINTVL,
ESPCONN_KEEPCNT
}
/** Current state of the espconn. Non-TCP espconn are always in state ESPCONN_NONE! */
enum espconn_state {
ESPCONN_NONE,
ESPCONN_WAIT,
ESPCONN_LISTEN,
ESPCONN_CONNECT,
ESPCONN_WRITE,
ESPCONN_READ,
ESPCONN_CLOSE
};
/** A espconn descriptor */
struct espconn {
/** type of the espconn (TCP, UDP) */
enum espconn_type type;
/** current state of the espconn */
enum espconn_state state;
union {
esp_tcp *tcp;
esp_udp *udp;
} proto;
/** A callback function that is informed about events for this espconn */
espconn_recv_callback recv_callback;//发送 回调 应该在连接成功回调函数里面注册
espconn_sent_callback sent_callback;//接受回调
uint8 link_cnt;
void *reverse; // reversed for customer use 断开连接?用的?
};
void ICACHE_FLASH_ATTR server_recv(void *arg, char *pdata, unsigned short len) {
os_printf("收到的数据:%s", pdata);//接受到的数据通过串口显示出来
//espconn_sent((struct espconn *) arg, "已经收到啦!", strlen("已经收到啦!"));
}
void ICACHE_FLASH_ATTR server_sent(void *arg) {//觉得烦,可以不注册
os_printf("发送成功!");
}
void ICACHE_FLASH_ATTR server_discon(void *arg) {
os_printf("连接已经断开!");
}
void ICACHE_FLASH_ATTR server_listen(void *arg) //注册 TCP 连接成功建立后的回调函数
{
struct espconn *pespconn = arg;
espconn_regist_recvcb(pespconn, server_recv); //接收
//espconn_regist_sentcb(pespconn, server_sent); //发送
espconn_regist_disconcb(pespconn, server_discon); //断开
}
void ICACHE_FLASH_ATTR server_recon(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
os_printf("连接错误,错误代码为:%d\r\n", err); //%d,用来输出十进制整数
}
void ICACHE_FLASH_ATTR tcp_server(uint32_t Local_port)
{
user_tcp_conn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空间
user_tcp_conn.type=ESPCONN_TCP;
user_tcp_conn.proto.tcp->local_port=Local_port; //本地端口
espconn_regist_connectcb(&user_tcp_conn, server_listen); //注册 TCP 连接成功建立后的回调函数
espconn_regist_reconcb(&user_tcp_conn, server_recon); //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
espconn_accept(&user_tcp_conn);
espconn_regist_time(&user_tcp_conn,180, 0);
}
我在官方的串口里面加了句话,让,电脑串口给esp8266发消息,会会通过tcp发给服务端,或者客户端
LOCAL void ICACHE_FLASH_ATTR ///
uart_recvTask(os_event_t *events)//接受到串口的处理
{
uint8_t Uart_fifo[100]={0};//存储接受到的数据
if (events->sig == 0) {
#if UART_BUFF_EN
Uart_rx_buff_enq();
#else
uint8_t fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
uint8_t d_tmp = 0;
uint8_t idx = 0;
for (idx = 0; idx < fifo_len; idx++) {//一个一个取出
d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
// uart_tx_one_char(UART0, d_tmp);
Uart_fifo[idx]=d_tmp;//那我就把他存进buff
}
// os_printf("Uart_fifo=%s",Uart_fifo);
espconn_sent(&user_tcp_conn,Uart_fifo,fifo_len);//通过tcp协议发送 //这是测试,应该要判断连接
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
uart_rx_intr_enable(UART0);
#endif
} else if (events->sig == 1) {
#if UART_BUFF_EN
//already move uart buffer output to uart empty interrupt
//tx_start_uart_buffer(UART0);
#else
#endif
}
}
接下来我学习json 格式,每次传输json格式,好处理,敬请期待