一起学习CC3200系列教程之Yeelink传数据

时间:2022-08-31 19:18:51

序:

能力有限,难免有错,有问题请联系我,

QQ1519256298     hytga@163.com

Pdf下载http://pan.baidu.com/s/1hqiWB56

 


为了提高博客的活跃,,如果你需要源代码,请留下邮箱,,,谢谢大家啊,,不然才两个评论,让我情何以堪啊

这个文档主要讲解怎么使用CC3200把数据传到Yeelink和怎么获取Yeelink上的数据。

关键字:Yeelink,TCP,HTTP,Socket,JSON,DNS,STA和AP模式

你可以先百度下上面的关键字,对这些最好有一个概念,因为别人讲的比较好。

 


Yeeklink:作为一个开放的公共物联网接入平台,目的是为服务所有所有的爱好者和开发者,使传感器数据的接入、存储和展现变得轻松简单。

TCP:一般性的建立TCP连接需要两个参数:IP 和端口。这里我们使用dns获取其ip,

HTTP:web浏览器使用的就是HTTP协议,这个是建立在tcp的基础上,本文只是简单地模仿了HTTP的格式,

Socket:怎么建立TCP连接,就需要用到socket,这个很像linux的socket。

Json:json是一种数据的传输格式,譬如    {"name":阿汤哥,"age":100 }    这个的数据的含义是:名字叫阿汤哥,年龄是100岁,,简单明了的协议。

STA:当CC3200需要连上路由器的wifi的时候就叫STA模式,,当用电脑连上CC3200的wifi就叫AP模式。



yeelink上的各种截图及结果截图

一起学习CC3200系列教程之Yeelink传数据


一起学习CC3200系列教程之Yeelink传数据



直接使用tcp测试工具把数据上传,

post上传数据

一起学习CC3200系列教程之Yeelink传数据


get,获取数据

一起学习CC3200系列教程之Yeelink传数据


结果:

一起学习CC3200系列教程之Yeelink传数据




软件流程:

首先,CC3200作为了一个STA,通过路由器的网络连上因特网,使用DNS获取Yeelink的ip,Yeelink的端口号是80端口,一般80端口是用作HTTP的,我们模仿HTTP的协议把数据传到Yeelink上,数据的传输格式是JSON格式 。


首先,需要在common找到如下的定义,并根据你的网络情况进行更改

#define SSID_NAME           "需要更改"    /* AP SSID */
#define SECURITY_TYPE       SL_SEC_TYPE_WPA_WPA2/* 加密类型,一般的都是这个Security type (OPEN or WEP or WPA*/
#define SECURITY_KEY        "需要更改"              /* Password of the secured AP */
#define SSID_LEN_MAX        32
#define BSSID_LEN_MAX       6
 


你的yeelink的设备号等相关信息:

//yeelink的设备地址,需要根据你的情况进行更改
#define mainYEELINK_DEVICE_ID		20555
//yeelink的传感器地址,需要根据你的情况进行更改
#define mainYEELINK_TestNum_ID		38264
//yeelink的key号,需要根据你的情况进行更改
#define mainYEELINK_API_KEY			"5d4c9fb6b2ba9386d497e6cf6a2a9f75"

//设备地址,需要根据你的情况进行更改
#define mainYEELINK_TestSwitch_ID		38265


HTTP的数据

//http的post数据格式,不需要更改
char g_cPostData[] = "POST /v1.1/device/%d/sensor/%d/datapoints  HTTP\/1.1\r\n"
		"Host:api.yeelink.net\r\n"
		"Accept: *\/\* \r\n"
		"U-ApiKey: %s \r\n"
		"Content-Length: %d \r\n"
		"Content-Type: application/json;charset=utf-8\r\n"
		"Connection: close\r\n"
		"\r\n"
		"%s";
//http的get数据格式
char g_cGetData[] = "GET /v1.1/device/%d/sensor/%d/datapoints  HTTP\/1.1\r\n"
		"Host:api.yeelink.net\r\n"
		"Accept: *\/\* \r\n"
		"U-ApiKey: %s \r\n"
		"Content-Length: 0 \r\n"
		"Connection: close\r\n"
		"\r\n\r\n";



我是直接使用官方的httpserver的例程进行更改的,设置是:使用freertos系统

创建任务,在main函数中更改

    //
    // Create HTTP Server Task
    //
    lRetVal = osi_TaskCreate(vYeelinkTask, (signed char*)"vYeelinkTask",
                         OSI_STACK_SIZE, NULL, OOB_TASK_PRIORITY, NULL );

任务:连接上网络,获取yeelink的ip,发送post数据和get数据

post数据:就是把你的数据传输到yeelink上,可以实现的功能:上传传感器的值

get数据:就是把yeelink的数据传到CC3200,可以实现的功能:远程遥控家里的设备

static void vYeelinkTask(void *pvParameters) {
	unsigned long ip,temp = 0;
	char buffer[20];
	UART_PRINT("success:%s %d\r\n",__FUNCTION__,__LINE__);
	scNetStaInit();
	delay();
	while(1) {
		ip = lGetYeelinkIp();
		if (ip != 0) {
			//这个主要就是实现JSON的数据
			//{"value":12}\r\n
			snprintf(buffer,20,"{\"value\":%d}\r\n",temp++);
			//这个主要就是合成HTTP协议
			//这个具体可以看g_cPostData
			snprintf(g_buffer,300,g_cPostData,mainYEELINK_DEVICE_ID,mainYEELINK_TestNum_ID,mainYEELINK_API_KEY,strlen(buffer),buffer);
			UART_PRINT("\r\n Send:\r\n%s\r\n",g_buffer);
			//发送数据,参数:数据,,数据长度,ip,端口
			vSendOneDataWithIpPort(g_buffer,strlen(g_buffer),ip,mainYEELINK_PORT);
			delay();
			delay();
			snprintf(g_buffer,300,g_cGetData,mainYEELINK_DEVICE_ID,mainYEELINK_TestSwitch_ID,mainYEELINK_API_KEY);
			UART_PRINT("\r\n Send:\r\n%s\r\n",g_buffer);
			vSendOneDataWithIpPort(g_buffer,strlen(g_buffer),ip,mainYEELINK_PORT);
			delay();
			delay();
		}
		delay();

	}
}



连接网络

//设置sta模式并连接到网络
//返回0 ,连接成功
//返回-1,连接失败
static signed char scNetStaInit(void) {
    SlSecParams_t secParams = {0};
    unsigned short len, config_opt;
    long lRetVal = -1;
    //主要是设置成默认的状态,这个在httpserver就有了
    lRetVal = ConfigureSimpleLinkToDefaultState();
    if(lRetVal < 0)
    {
        if (DEVICE_NOT_IN_STATION_MODE == lRetVal)
            UART_PRINT("Failed to configure the device in its default state\n\r");

        LOOP_FOREVER();
    }
    //需要先调用这个
    lRetVal = sl_Start(0, 0, 0);
    if (lRetVal < 0)
    {
        UART_PRINT("Failed to start the device \n\r");
        LOOP_FOREVER();
    }
    // staring simplelink
    g_uiSimplelinkRole =  sl_Start(NULL,NULL,NULL);

    // 设置成sta模式
    if(g_uiSimplelinkRole != ROLE_STA )
    {
        //Switch to STA Mode
        lRetVal = sl_WlanSetMode(ROLE_STA);
        ASSERT_ON_ERROR(lRetVal);
        
        lRetVal = sl_Stop(SL_STOP_TIMEOUT);
        
        g_usMCNetworkUstate = 0;
        g_uiSimplelinkRole =  sl_Start(NULL,NULL,NULL);
    }
    //密码
    secParams.Key = (signed char*)SECURITY_KEY;
    //密码长度
    secParams.KeyLen = strlen(SECURITY_KEY);
    //加密类型
    secParams.Type = SECURITY_TYPE;
    //进行连接,参数有 SSID ,密码
    lRetVal = sl_WlanConnect((signed char*)SSID_NAME, strlen(SSID_NAME), 0, &secParams, 0);
    ASSERT_ON_ERROR(lRetVal);
    //判断有没有连接成功。其实就是判断g_ulStatus响应的位有没有设置成功
    //g_ulStatus的值在SimpleLinkWlanEventHandler这个函数内被更改
    //SimpleLinkWlanEventHandler是一个回调函数,主要的就是作用就是
    //当CC3200连上网络或者断开网络的时候会被调用
    while((!IS_CONNECTED(g_ulStatus)) || (!IS_IP_ACQUIRED(g_ulStatus)))
    {
    	//进行循环,等待成功

    }
    return 0;

}



获取yeelink网址对应的ip地址,使用的是dns服务

//获取yeelink网址对应的ip地址
unsigned long lGetYeelinkIp(void) {
	unsigned long ip;
	signed int retval;
	retval = Network_IF_GetHostIP(mainYEELINK_SITE,&ip);
	if (retval < 0) {
		return 0;
	} else {
		return ip;
	}
}
//这个函数是我从nerwork_if文件拷贝出来的.不能直接包含那个文件
//因为会引起重复定义的错误。所以你直接
long Network_IF_GetHostIP( char* pcHostName,unsigned long * pDestinationIP )
{
    long lStatus = 0;
    //利用这个函数就可以把www。yeelink。net转成IP,,
    //当然你也可以不用这个函数,,直接把IP规定住,
    //怎么手动查www。yeelink。net:   win系统下,ping一下这个www。yeelink。net网址就会出现ip信息
    lStatus = sl_NetAppDnsGetHostByName((signed char *) pcHostName,
                                            strlen(pcHostName),
                                            pDestinationIP, SL_AF_INET);
    ASSERT_ON_ERROR(lStatus);


    UART_PRINT("Get Host IP succeeded.\n\rHost: %s IP: %d.%d.%d.%d \n\r\n\r",
                    pcHostName, SL_IPV4_BYTE(*pDestinationIP,3),
                    SL_IPV4_BYTE(*pDestinationIP,2),
                    SL_IPV4_BYTE(*pDestinationIP,1),
                    SL_IPV4_BYTE(*pDestinationIP,0));
    return lStatus;


}


发送数据

char g_buffer[300];
//发送数据给指定的ip和端口号,只有一次
//执行过程
//1、新建连接
//2、发送数据、
//3、断开连接
void vSendOneDataWithIpPort(unsigned char *data,unsigned long len,unsigned long ip,unsigned long port) {

    SlSockAddrIn_t  sAddr;
    int             iAddrSize;
    int             iSockID;
    int             iStatus;
    int count = 0,size;
    //filling the TCP server socket address
    //使用的是socket
    //这个我忘了,基本是固定不变
    sAddr.sin_family = SL_AF_INET;
    //端口信息,
    sAddr.sin_port = sl_Htons((unsigned short)port);
    //ip信息
    sAddr.sin_addr.s_addr = sl_Htonl((unsigned int)ip);

    iAddrSize = sizeof(SlSockAddrIn_t);

    // creating a TCP socket
    //创建一个tcp连接
    iSockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
    if( iSockID < 0 )
    {
    	UART_PRINT("Error:%s %d\r\n",__FUNCTION__,__LINE__);
    }

    // connecting to TCP server
    //连接到tcp的服务器,参数:socket的句柄,目的地址信息
    iStatus = sl_Connect(iSockID, ( SlSockAddr_t *)&sAddr, iAddrSize);
    if( iStatus < 0 )
    {
        // error
    	iStatus = sl_Close(iSockID);
    	if (iStatus < 0)
    		UART_PRINT("Error:%s %d\r\n",__FUNCTION__,__LINE__);
    }
    //连接完成最好不要直接就发送数据,经我的测试是,马上发送数据可能会成功,但是数据却没有传过去
    delay();
    //发送数据,参数:socket的句柄,数据指针,数据长度,最后一个参数没有作用
    iStatus = sl_Send(iSockID, data, len, 0 );
    if( iStatus <= 0 )
    {
        // error
    	iStatus = sl_Close(iSockID);
    	if (iStatus < 0)
    		UART_PRINT("Error:%s %d\r\n",__FUNCTION__,__LINE__);
	}
    //接收数据。,参数:sockeet的句柄,缓冲区,缓冲器大小,返回的是接收的数据大小
    //请注意这个函数可能是阻塞的
    //阻塞的意思就是,会一直等到有数据才返回,或者有问题才返回
    size = sl_Recv(iSockID,g_buffer,300,0);
    transHeader =  (SlTransceiverRxOverHead_t *)g_buffer;
    g_buffer[size] = 0;
    UART_PRINT("\r\nReceive:\r\n%s\r\n",g_buffer);
    //关闭连接
	iStatus = sl_Close(iSockID);
	if (iStatus < 0)
		UART_PRINT("Error:%s %d\r\n",__FUNCTION__,__LINE__);

}

到这里基本上所有的代码都已经上传完毕,,