uip的yeelink实现

来源:互联网 发布:什么便签软件好看 编辑:程序博客网 时间:2024/06/17 02:34

前言

物联网的IPV6应用是一个趋势,contiki是集成了6lowpan的一个集成开发工具。uip是集成在内部的,支持IPV6以及IPV4,这里先通过IPV4与平台连接建立一个数据通道。后续会跟进IPV6以及6lowpan的应用。而且uip不需要OS支持,以事件驱动的方式编程,占用的RAM以及ROM都符合嵌入式的需求。

之前我们需要了解一些背景知识:

1,http的相关知识

2,yeelink http请求格式分析 (分析很透彻)

3,tcp/ip的连接

4,stm32平台+enc28j60网络模块

5,uip1.0 (contiki里面的uip已经是与6lowpan、ipv6耦合起来了,所以这里选择了uip1.0的版本)uip0.9 refman中文翻译 也是一个不错的博文,让大家更快熟悉uip的编程思想。

移植

这一部分我们会先介绍uip在stm32平台上的移植工作。Enc28j60是带SPI 接口的独立以太网控制器,可以用mcu控制spi来实现tcp/ip数据流的收发,所以要先完成Enc28j60的驱动程序,再整合Uip。

这一部分可以参考:uip在stm32上的移植,说明的也很详细,我就不累赘了。

软件实现

1,DNS

uip自带了一个dns的解析,配置如下:

void yeelink_init(void){    uip_ipaddr_t ipaddr;    resolv_init();    uip_ipaddr(ipaddr, 221, 228, 255, 1); // DNS    resolv_conf(ipaddr);    resolv_query(YEELINK_HOST);}
这里的DNS我们可以通过查看自己的网络参数获取。当然你也可以配置uip为DHCP模式,这样就会自动帮我们配置DNS查询上级IP。

当查找到目的网址的IP或者说查找失败,都会调用void resolv_found(char *name, u16_t *ipaddr);这个函数需要我们在main里自己实现:

void resolv_found(char *name, u16_t *ipaddr){    if (ipaddr == NULL) {        printf("Host '%s' not found.\r\n", name);    } else {        printf("Found name '%s' = %d.%d.%d.%d\r\n", name,               htons(ipaddr[0]) >> 8,               htons(ipaddr[0]) & 0xff,               htons(ipaddr[1]) >> 8,               htons(ipaddr[1]) & 0xff);        yeelink_connect(YEELINK_HOST, YEELINK_PORT);    }}

如果查找到了yeelink的地址,我们就进行tcp连接。

2,client实现

剩下就是yeelink的client实现,代码如下:

void yeelink_client_appcall(void){    if (uip_connected()) {        yeelink_request_get();        printf("yeelink_client: connected, waiting for data...\r\n");        return;    }    if (uip_aborted()) {        printf("yeelink_client: connection aborted\r\n");    }    if (uip_timedout()) {        printf("yeelink_client: connection timed out\r\n");    }    if (uip_acked()) {        yeelink_request_acked();    }    if ( uip_rexmit() || uip_newdata()) {        yeelink_newdata(); // 这里的数据是分包发送过来的        return;    }    if (uip_poll()) {        if (yeelink_poll()) {            return;        }    }    if (uip_closed()) {        yeelink_closed();        printf("yeelink_client: connection closed\r\n");    }}

这个流程按照uip的网络编程流程来,这里需要注意几点:

1,分包

http请求是根据mss来决定一包里面的有效数据长度的。这里就出现了yeelink的http应答分包发送,那么我们在处理http数据的时候就需要考虑到组包。实现的时候我取了个巧。

static void yeelink_newdata(void){    yeelink_client.timer = 0;    u16_t len = uip_datalen();    memcpy(yeelink_client.data, uip_appdata, len);    //{"timestamp":"2014-03-25T13:40:47","value":0}    u8_t *value_info = (u8_t *)strstr(yeelink_client.data, "\"value\"");    if (value_info != NULL) {   // 分片传送的        len = strlen("\"value\":");        u8_t status = *(value_info + len);        if (status == '0') {            printf("yeelink_client: switch is close\r\n");        } else {            printf("yeelink_client: switch is open\r\n");        }        memset(yeelink_client.data, 0x00 , WEBCLIENT_CONF_MAX_URLLEN);        /*uip_close();*/        yeelink_struct_init();    }}

2,查询时间周期

查询的时候似乎并没有时间限制,我在poll里面设置了1s查询一次,结果也依然可以返回。之前提到的5s限制并不存在,不知道是否是升级了服务。



总结:

uip相对于lwip而言会更适合物联网的开发,但是编程相对lwip而言会需要一些技巧性,因为与我们常规的阻塞式编程有区别。

代码的地址如下:https://utopiaprince@bitbucket.org/utopiaprince/uip1.0-stm32-webserver 可以用hg clone。

1 0
原创粉丝点击