uip的yeelink实现

前言

物联网的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。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值