本帖最后由 freebsder 于 2015-5-31 00:43 编辑
freebsder写在EEWorld,如需转载可以找 @soso 商量。
CC3200做节点的web服务:2、CC3200环境
这次不折腾功耗,这鸟东西和可用性凑在一起确实繁琐,功能完整性证明起来很麻烦。另外本人不以CC3200为生,也没兴趣每一个点都去折腾,只撸一些自己感兴趣应用场合又较多的地方(当然就是http了,这东西太有用)。下面也不能完全记录,太繁琐,有些我觉得很自然的操作步骤,可能就调过鳓。
0、
参考资料
CC32xx TechnicalReference Manual:swru367
CC3200 WirelessMCU Programmer's Guide:swru368
http://software-dl.ti.com/ecs/cc31xx/APIs/public/cc32xx_simplelink/latest/html/index.html
CC3200SDK_1.1.0
很遗憾的是TI似乎没有公布NP coprocessor的寄存器资料,只能找到SimpleLink的API参考,所以基础接口比如socket只好用ROM里提供的。而socket之上的应用协议比如http,有能力和精力的朋友如果觉得ROM自带的不方便,倒是可以自己写。TI SDK里确实提供了一个很好的参考:CC3200SDK_1.1.0\cc3200-sdk\netapps\http\server 。
1、
代码
虽然TI 没有给出ROM中SimpleLink代码,但是在SDK的代码里给了另外一份Server代码 CC3200SDK_1.1.0\cc3200-sdk\netapps\http\server,简单翻了一下,验证了一下,ROM Server(ROM里固化的Server,下面简写成RS)和User Server(用户自己实现的Server,下面简写成US)有几点区别。1、US响应浏览器请求较慢;2、US代码因为把协议层交给了用户,所以很方便的可以使用串口打印调试信息和状态;3、US代码因为把协议层交给了用户,所以RS中一些固定的服务端变量,如各种__SL_Pxxx,就需要自己用SimpleLink其他config相关的API实现;4、US代码因为把协议层交给了用户,所以对资源的解析和使用,可以根据自己的应用来处理,扩展性和移植性得到加强;5、RS速度快,功耗底,模式固定,适合简单应用的快速开发;6、还没发现。
2、
解析、状态
里面核心的三个文件依次是httpcore.c,httpdynamic.c,和httpstring.c。core对http请求进行解析和处理,dynamic对资源进行处理,string对文本进行处理(搜一下有没有token这个单词?所以别弄错了,这里不是通信,token不做令牌解释,这是text processing,不信?再去netapps下的json搜搜看),剩下的编码、验证、socket等等就不折腾了,标准的http那一套解释,这套体系虽然跑在单片机上可真没特殊的(只是具体实现和资源配置不一样),毕竟像第一章说的,CC3200只是一个小环节,它只能适应外面的世界。
这里可以看到很经典的socket编程,什么open啊,recv啊等等,直接把所有收到的包交给HttpCore_HandleRequestPacket处理,而下面毕竟CC3200是一个network processor,对这里面的数据进行过处理,这部分材料没有公开,所以就不深究了,反正就知道浏览器请求的一堆数据来了。
HttpCore_HandleRequestPacket是一个典型的状态机,connections的connectionState作为状态指示。太典型的一个状态机,代码本身没必要多解释。里面可以看到HttpConnectionState的各种状态。
大致说,首先解析httprequest第一行里面的GET POST和资源,然后根据http协议的约定取得头部,最后取得request body,好了,都取到了,那么就开始处理请求把,处理请求其实也就是填充response的过程,处理完了,response也就构造好了,把response返回给浏览器这个过程就结束了。在httpheaders.h中可以看到很熟悉的http的内容。
3、
弄个工程
现在是User Server,所以,东西都交给你来处理,包括服务端变量,资源引用,随便你怎么折腾。
不过首先要改造一下CC3200的oob。
在oob的main.c里,用HttpServerInitAndRun来启动应用,别忘记了编译连接的时候把上面说的那个server连接进去(偷了点懒)。
SetResource中,可以看到,/no_content(http server内部把大写转成小写来着)是作为resource来标识的。这是什么意思?第一no_content在我们的html资源中是没有的,是虚拟资源;第二,对这个资源还能挂载一个回调函数,简单起见我写的postCall和getCall,第一个参数0是post,1是get。这种处理方式在web中叫资源匹配,或者叫router或者叫resource dispatch或者叫filter(可不是滤波器啊不是滤波器)或者叫拦截器,反正一堆名字吧,都差不多一个意思。
4、
回调
好了,咱动态了,动态了。打开UART debug,
等待ap连接
好,来了个入网请求
浏览器来请求了:
断点
继续跑,再请求一下param_demos.html呢?
还记得,之前oob里面,params_demos.html里面的__SL_UXXX被替换成了什么?怎么在这里,服务器直接就把params_demos.html原封不动的发还给浏览器了?原来,__SL_UXXX就不是什么令牌的意思啊,一下就现原形了。
没关系,看这里
经过静态文件的查找,读取,调用ROM api把params_demos.html读到缓冲区了。是的,这里没有经过任何处理。
但是,不要忘记http的基础是文本,我们可以在断点前面加上我们自己的处理函数,把__SL_Uxxx处理成我们自己的值,比如adc采样?比如led状态?都不是问题。关键是要知道__SL_Uxxx只是SimpleLink RS中默认的服务端变量,甚至我们可以把自己定义的服务端变量折腾成比如php的形式 getadc ?>, 折腾成jsp的形式 <%getled %> <% __SL_Uxxx %>。文本已经读到缓冲区了,不要问我文本该怎么处理。。。
TI这个Http server比较简单,写的也很清晰,实体资源或者说静态资源的处理应该比较清晰了。
现在我们来处理虚拟资源或者说动态dynamic资源,post一个/led吧让第1个led打开。
这里用python构造了一个简单的post请求
import urllib
import urllib2
url ='http://mysimplelink.net/led'
values ={'instance':'1','action':'on'}
data =urllib.urlencode(values)
print data
req =urllib2.Request(url, data)
response =urllib2.urlopen(req)
the_page =response.read()
print the_page
在http server代码里,我们需要在HttpDynamic_ProcessRequest中,把request传进我们自己的处理句柄。
/* 1. Call userdefined API */
contentBody.pData=g_RestContent[g_NumResource].pCbfunc((void*)&request->requestContent);
毕竟http server只是个框架,完全可以自己根据需求加工。
Oob的HttpServerInitAndRun之前添加:
static char POST_LED[] = "/led";
SetResources(0,POST_LED, postLed);
添加处理句柄:
struct HttpBlob
{
unsigned short uLength;
unsigned char* pData;
};
unsigned char*postLed(void *params)
{
struct HttpBlob *p = params;
return p->pData;
}
上图调试窗口看到把request原封不动传进来了,剩下的又剩文本处理了。解析instance,解析action,然后把第1个led的GPIO置on吧。
5、
应用层怎么搞?
比如上面简单的python代码:
import urllib
import urllib2
url ='http://mysimplelink.net/led'
values ={'instance':'1','action':'on'}
data =urllib.urlencode(values)
print data
req =urllib2.Request(url, data)
response =urllib2.urlopen(req)
the_page =response.read()
print the_page
也可以jquery在html里弄,重点是构造一个post/get请求,就行了,这体现出http很强大的一个特点:文本,跨平台,跨语言。而返回的数据,不管是jquery的repsonse还是python的response.read(),拿到你手里了,完全就剩你的工作了。