Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

1.前言

    【2014年4月重写该博文】
    经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Thread的帮助下却很快实现了yeelink平台的应用。
    【选择STM32理由】
    1.常用的32位MCU,Cortex-M3内核,运算速度快,RAM和FLASH容量较大。
    2.价格便宜,很容易买到。
    【选择RT-Thread理由】
    1.RT-Thread具有丰富的组件包括LwIP,省去了移植网络协议栈的困扰。
    【网卡芯片ENC28J60】
    1.SPI接口,占用较少的GPIO,适合引脚数较少的MCU。
    2.价格便宜,容易买到。

2.有用的资料

    【代码仓库
    代码仓库位于CSDN Code,方便交流。请不要使用任何版本的IE浏览器打开代码仓库,请使用谷歌或者火狐浏览器,如果使用国产双核浏览器,请切换至极速模式。在博客和代码仓库留言中我经常发现无法下载代码的情况,我再windows和ubuntu中反复实验始终没有问题,后来才才发现我除了买火车票之外从来不用IE浏览器,而很多网友使用了低版本的IE浏览器,低版本的IE浏览器正是问题所在。
    【相关博文】
    【Yeelink Http请求格式分析】
    【Yeelink平台查询开关量——套接字编程 Windows平台】——如果还不熟悉RT-Thread或者socket的话,试试这个吧。
    【平台说明】
    RT-Thread版本1.2.0
    编译器版本:IAR EWARM 6.5
    【操作说明】
    【1.1请务必修改Http请求内容——见tcpclient_yeelink.c,包括设备编号,传感器编号和用户API
    【1.2请详细核对ENC28J60相关接口,包括SPI接口,中断接口,相关时钟等。请认真修改enc28j60.c和stm32f10x_it.c中相关函数。如果SPI总线上还有其他设备,请务必确认该从设备CS端口存在上拉电阻或把与CS端口连接的GPIO端口配置为输出高电平。
    【1.3】由于ENC28J60无法自动识别交叉线和非交叉线,请把目标板连接路由器
    【1.4】如果您还是学生,并且您所在的高校需要通过网页拨号上网,你可能无法成功运行以下代码。我只能说一声抱歉了。

    【2】请务必修改目标板IP地址(路由器地址和子网掩码),默认的IP地址为192.168.1.30——见rtconfig.h,目标板并没有打开DHCP。
#define RT_LWIP_IPADDR0192
#define RT_LWIP_IPADDR1168
#define RT_LWIP_IPADDR2
#define RT_LWIP_IPADDR3 30
    【3】请先查看目标板IP地址,建议使用putty。待目标板启动之后按下tab键,可查看目标板支持的指令。之后输入list_ip()——查看目标板IP地址相关信息,等同于windows中的ipconfig和linux中的ifconfig。

Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32_第1张图片
图1 按下TAB键
Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32_第2张图片
图2 查看IP地址
【4】输入httpclient() 执行HTTP请求。仅执行一次HTTP请求。

图3 HTTP请求结果
【5】代码以CSDN代码仓库为准

3.参考代码

#include <rtthread.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include <led.h>
// Http请求内容
static const char send_data[] =
"GET /v1.0/device/1949/sensor/2511/datapoints HTTP/1.1\r\n"
"U-ApiKey:[your apikey]\r\n"
"Host: api.yeelink.net\r\n\r\n";
void tcpclient(const char* host_name, int port)
{
    (void)port;
   
    char *recv_data;
    int sock, bytes_received;
   
    struct hostent *yeelink_host;
    struct in_addr yeelink_ipaddr;
    struct sockaddr_in yeelink_sockaddr;
   
    recv_data = rt_malloc(1024);
    if (recv_data == RT_NULL)
    {
        rt_kprintf("No memory\r\n");
        return;
    }
    // 第一步 DNS地址解析
    rt_kprintf("calling gethostbyname with: %s\r\n", host_name);
    yeelink_host = gethostbyname(host_name);
    yeelink_ipaddr.s_addr = *(unsigned long *) yeelink_host->h_addr_list[0];
    rt_kprintf("Yeelink IP Address:%s\r\n" , inet_ntoa(yeelink_ipaddr));
   
   
    yeelink_sockaddr.sin_family = AF_INET;
    yeelink_sockaddr.sin_port = htons(80);
    yeelink_sockaddr.sin_addr = yeelink_ipaddr;
    rt_memset(&(yeelink_sockaddr.sin_zero), 0, sizeof(yeelink_sockaddr.sin_zero));
   
    while(1)
    {
        // 第二步 创建套接字
        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            rt_kprintf("Socket error\n");
            rt_free(recv_data);
            return;
        }
       
        // 第三步 连接yeelink
        if (connect(sock, (struct sockaddr *)&yeelink_sockaddr, sizeof(struct sockaddr)) == -1)
        {
            rt_kprintf("Connect fail!\n");
            lwip_close(sock);
            rt_free(recv_data);
            return;
        }
       
        // 第4步 发送Http请求
        send(sock,send_data,strlen(send_data), 0);
       
        // 第5步 获得Http响应
        bytes_received = recv(sock, recv_data, 1024 - 1, 0);
        recv_data[bytes_received] = '\0';
       
        // 响应内容为 {"timestamp":"2013-11-19T08:50:11","value":1}
        // 截取“value”之后的内容
        char* actuator_info = rt_strstr( recv_data , "\"value\"");
        int offset = rt_strlen("\"value\":");
        actuator_status = *(actuator_info + offset);
        rt_kprintf("actuator status :%c\r\n",actuator_status);
       
        // 获得开关状态,并设置LED指示灯
        char actuator_status;
        (actuator_status == '1')?rt_hw_led_on(0):rt_hw_led_off(0);
       
        rt_memset(recv_data , 0 , sizeof(recv_data));
       
        // 关闭套接字
        closesocket(sock);
       
        // 延时5S之后重新连接
        rt_thread_delay( RT_TICK_PER_SECOND * 5 );
    }
}

4.总结

    千辛万苦尝试LwIP+Yeelink,但是最终实现起来却非常简单。接下来可以尝试使用Yeelink做一些具体的应用,初步想法做一个智能鱼缸,希望前面的道路可以顺利一些。


你可能感兴趣的:(thread,rt,yeelink,Lwip,ENC28J60)