微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > CC3200做节点的web服务:3、CC3200 httpserver

CC3200做节点的web服务:3、CC3200 httpserver

时间:10-02 整理:3721RD 点击:


freebsder写在EEWorld,如需转载可以找 @soso 商量。

CC3200做节点的web服务:1、体系简介(generic)

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 ?>, <?__SL_Uxxx?> 折腾成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(),拿到你手里了,完全就剩你的工作了。

我不牛,我只是说我知道的东西。

httpserver和browser之间的基本交互错误就不在重复了,这里只说为什么方法也是错的。

每个问题有自己的问题域,problem domain,这是为什么统计里面要叫样本而不是集合,为什么明明是可数序列却在信号处理里面叫它离散信号。而这个problem domain有自己的建模、方法和关注点,domain的隔离和区分是分析问题的边界与基础。这也是为什么电子学里要专门开设一个高频电路,这也是为什么接近光速的物体不能用牛顿力学来建模。
同样的,在httpserver这个问题上,关注的是server的提供,而不是如何通信,它需要通信没错,可通信不是关注点。如何通信是tcp/ip的问题,tcp/ip这个problem domain的关注点才是通信(如果通信问题都还要http考虑的话,还要tcp/ip这一层做什么?)。http本身关注的是协议文本的语意,这个语意是一种应用程序规范,只不过这种规范是国际公认大家遵守的规范。比如各种content的意义,GET/POST/PUT/DELETE的意义,URI的意义等。而server的作用是如何、何时、怎样针对这些语意要求提供服务。server这个单词是httpserver的核心,是解析语意之后的语意服务。就比如英文都知道是由字母组成的,可是你用教字母的方法来教英文的文法,这就是错的。你试图用通信的领域知识来建模语意解析和语意服务这个领域,这方法难道不是错的吗?如果方法正确了,会写出基本交互模型都是错误的内容?
复杂吗?确实,对一个入门书籍来说确实显得复杂,所以我一开始就说你可以不细说,但是脉络你可以花点文字画点图概括整体框架。

谢谢 @freebsder

这种帖子要加精华,

我自己写的帖子加不加无所谓,SOSO加了一个了,@chenyy 提到的那个老师的乱写的帖子,我觉得才应该给我加精华,老师的德行都被他自己败光了,我就当去伪存真嘛,哈哈。

看了一下那个帖子,不太了解前因后果,老师的书呢,没见啊,不做品论了。
物联看起来很low,真的能搞的不多,涉及的东西还是有点多,关于互联网的一些东西,也不大懂,不知道有多少搞嵌入式的懂get和post这些玩意的背后是啥。
互联网像今天这么发达,前人做的贡献不是一点点,什么rfc文档有多少,不太清楚
REST框架呢,。。哎,太复杂了,我要去学习了。

@soso 精华帖

样章
http://bbs.eeworld.com.cn/forum. ... &fromuid=551466
CC3200 Wi-Fi MCU应用基础8.pdf

确实涉及的东西比较多,单独一个点拿出来都是一个不小的方向。

看了一眼,用不上,看代码也一样
这种书籍适合一般工程院校实验课程或者初级工程师使用

海纳百川,有容乃大

TI的MCU代码,不知楼主看过没有?

*****************************************************************************
//
//! This function gets triggered when HTTP Server receives Application
//! defined GET and POST HTTP Tokens.
//!
//! \param pHttpServerEvent Pointer indicating http server event
//! \param pHttpServerResponse Pointer indicating http server response
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pSlHttpServerEvent,
SlHttpServerResponse_t *pSlHttpServerResponse)
{
unsigned char strLenVal = 0;

if(!pSlHttpServerEvent || !pSlHttpServerResponse)
{
return;
}

switch (pSlHttpServerEvent->Event)
{
case SL_NETAPP_HTTPGETTOKENVALUE_EVENT:
{
unsigned char status, *ptr;

ptr = pSlHttpServerResponse->ResponseData.token_value.data;
pSlHttpServerResponse->ResponseData.token_value.len = 0;
if(memcmp(pSlHttpServerEvent->EventData.httpTokenName.data, GET_token,
strlen((const char *)GET_token)) == 0)
{
status = GPIO_IF_LedStatus(MCU_RED_LED_GPIO);
strLenVal = strlen(LED1_STRING);
memcpy(ptr, LED1_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
if(status & 0x01)
{
strLenVal = strlen(LED_ON_STRING);
memcpy(ptr, LED_ON_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
}
else
{
strLenVal = strlen(LED_OFF_STRING);
memcpy(ptr, LED_OFF_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
}
status = GPIO_IF_LedStatus(MCU_GREEN_LED_GPIO);
strLenVal = strlen(LED2_STRING);
memcpy(ptr, LED2_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
if(status & 0x01)
{
strLenVal = strlen(LED_ON_STRING);
memcpy(ptr, LED_ON_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
}
else
{
strLenVal = strlen(LED_OFF_STRING);
memcpy(ptr, LED_OFF_STRING, strLenVal);
ptr += strLenVal;
pSlHttpServerResponse->ResponseData.token_value.len += strLenVal;
}
*ptr = '\0';
}

}
break;

看不懂我写什么就别开腔,说越多越暴露无知。

你小子也太缺少礼貌了。
我承认你Web技术比我强,但CC3200是需要MCU和Web协调工作的,离开了MCU,你还和我谈什么CC3200。
我从教30年了,你小子就凭一个样章就给我下结论未免太片面了。
再有,你那是讨论问题的态度吗?一上来就指责别人这乱说那乱说,能不能把正确结果告诉大家。
你能否告诉大家:HTTP GET TOKEN VALUE是什么意思?

不会就不会,别煮熟的鸭子嘴硬。你不是神,你也不是万能。
你一边承认自己知识的缺失,在人给你指出之后一边又东拉西扯找各种理由来为自己乱写开脱,一边嘴上说由于编者xxx有限,请广大读者指错,一边又死不认错。已经告诉你这一章基本模型都写错了,基础都错了,还死硬的把方法和内容搬出来开脱。你以为工程上的东西是高考给你过程分步骤分结果分?!你一开始不知道错了我觉得是人都犯错,这无可厚非,可是指出你错了,还不认错,还方法论内容论,这就是写书人、老师的良心了。
这是技术,不是内斗,摆资格没用,错了就是错了,你就是主席,也有人说你错,最基本的http模型都被你搞错了,你好意思说你方法正确?
承认个错误对老师来说就是个十分丢面子的事情吗?你们祖师爷孔老夫子几千年前就告诉你不耻下问,组训忘了?!

你教多少年对我来说都没用,我29岁就帮博导带博士。

另外,要掐架你也仔细看清楚。
一,我从来都是只针对样章来说,下的技术结论也是针对你的样章。
二,对于一个老师,明知自己的错误后东拉西扯,讲出内容不重要方法重要。首先你方法就是错的,告诉过你,http就是http server就是server,不是通信,你非要用通讯那一套“建立连接,发送请求,接收应答,断开连接。”来解释,你这不是自己找不自在?知道为什么分析函数到统计里面就成随机变量?知道什么是问题域吗?你用一个问题领域来建模另一个问题领域,你还说你方法是对的?
三,我对你没结论,我是对中国的“老师”群体下结论。
四,我说那书没什么价值,是你还是我跳出来摆30年老师资格请问版主不学会走能会跑?你开始怎么不问为什么这么说?是你这样谦虚的教别人走路的吗?
五、对于误人子弟而无自知的老师,凭什么想要赢得人的尊重?

至于HTTP GET TOKEN VALUE是什么意思,我前面写了,也讲了,实在不懂还有baidu,google(哦,对不起,也是被你们老师搞了墙出不去),或者你还有其他优秀学生可以去不耻下问。
强调方法的老师能问出这样内容性的问题,我挺佩服你。

也不和你多费口舌了,这样说吧,我看不起的是那种犯了错不仅不承认,当被驳斥的体无完肤的时候又唧唧歪歪拿出一堆理由为自己开脱,还指责别人为什么不尊敬老师。。。
请不要忘了你是老师,你是在教书育人,你培养的都是未来的工程师,一个连正确性都不能教的老师,你让学生,让未来的雇主怎么尊敬你?!

看来你比我牛多了,我不知你学的什么专业,我只知道HTTP是基于TCP/IP的超文本传输协议,而通信就是信息的传输,HTTP竟然不是通信,而是server。

server是干什么用的,是给client提供服务的,怎么提供,通过通信。你可能是高层协议用多了,而忽略了低层协议是如何工作的。

讨论问题先把问题讨论清楚再说,先不要进行人身攻击。

我可没攻击你,我说的是那些不负责任的“老师”。



任何人都会出错,这不是问题,不就是个错嘛,改了就完了呗,我鄙视的是那些不负责任,死不肯认错,东拉西扯以证明自己没错,教书教不正确还振振有词的老师群体。
注意是群体,至于你到底怎么样,我不知道。



你这逻辑就是错的,你企图用一个外延来解释内涵。你这逻辑,就是“英文是干什么用的?是为人类提供交流用的,怎么提供,通过26个字母。”好吧,不否认英文是字母组成的,可是你一个说英文(httpserver)的章节,你告诉大家26个字母(通信)是什么。

另外,http里那个 t,transfer,是传输啊,不是communication,不是通信啊,不是htcp啊。token,是记号啊,不是令牌啊,洋鬼子的多音词通假字,可你不能到哪里都只认你熟悉的那个音吧。

低层协议?老师啊老师,分层网络啊分层网络,基本的概念啊基本的概念啊,基本的分层抽象啊基本的分层抽象啊! 你每一层都去关心通信,你还要mac层,要tcp/ip层做什么?

再说了,哪里是什么通讯啊?那是你自己臆想的“网页发出GET __SL_Uxx令牌”这种“通讯”,就是我前面说的你用通信的领域知识来给httpserver建模,可真不是你想的这样啊老师!所以我说你这样章内容也错了,方法也错了呢,方法错了直接导致内容就错了。查查资料嘛,从我说你样章有问题,到现在已经快一周了,现在还在纠结通讯,我很捉急啊!学校那么多书,为什么就不去借来看看呢?基本,最基本的browser,http server交互模型是怎样的?实在不行问问搞过web的学生或者同事嘛。

另外啊,你也承认我web比你接触的多,不夸张的说就这一点我确实比你接触的多,可我实在不明白为什么一定要用自己不擅长的一面来证明自己的正确?

首先,我在此明确的承认,我HTTP的解释是错误的,我用底层的概念去解释高层的应用。
自始自终,我没有说我关于HTTP的解释是正确的,我只是想搞明白,我错在哪里。
Web确实不是我擅长的领域,涉及他也是TI的例程用到了,当初写时由于时间关系没有做深入的研究,误导了初学者,在此我表示衷心的道歉!也请高手们多批评指正,多谢!

我在学校的时候也帮老板弄过书,毕业之后买的坑书太多了,被误导的弯路也太多了,所以我个人对这种误人子弟的人和事十分反感,以至于前面态度不好,向您道歉,您大人大量别生气啊

HTTP是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于Web浏览器和Web服务器之间的双工通信。
摘自《HTTP权威指南(HTTP:The Definitive Guide)》前言第一段。
另:HTTP GET TOKEN VALUE的谷歌和有道翻译都是HTTP GET令牌值。

好吧,当我看到“另”里面的话,我真的笑了,发自内心的笑了,一个学者怎么可以简单到把外文资料的在线翻译当作正确解答呢?从一开始就在说,http的基础是文本、语意、文法,token不做通信令牌解。到现在还是既不考虑语境,也不考虑语意,连简单的一词多意也不考虑,更不要说信达雅这种高级要求,我已经无力吐槽了。当然,我不是学者,会许学术界用有道翻译和谷歌翻译就是严谨的代表呢也说不定。

说什么好呢?前面说了那么多关于 关注点、problem domain的意义和划分、语意、应用,谁也没否认httpserver需要通信,可居然还在纠结是不是通信。对于这个我也不多说了,既然你手里有书,那你花30秒翻翻目录嘛,看看6,700页的书有哪些内容是在说你认为的“通信”,也翻翻相关RFC文档,看看有哪些内容是在说你认为的“通信”嘛。

note:
我已经无力吐槽,也真不知道该如何讲讨论继续下去,说直接点吧,每个人都有知识局限,这是所有人都承认的吧,你也承认web只因为ti的例程有所以才接触,知识局限导致讨论的内容有真空你理解不了,这很正常,也没什么大不了,谦虚学习就好了呗,可学习之外请不要用非常不严谨的方法和论点来给自己佐证保面子,不是说好的方法比内容重要吗?如此不严谨就是所谓的方法?

可以体会为什么写书是良心活吗?一开始初学者就接受一个错误的观点,后面纠正起来该有多难!

没把大牙笑掉吧。
请你回答一个最基本的问题:什么是通信?

你也别问了,也别继续秀下限了,你中文都看不明白什么意思:“HTTP是在万维网上进行通信时所使用的协议方案。”主谓宾形状补你搞清楚了吗?看见一个“通信”就跑。也能理解你为何英文短语敢用有道词典直翻。
如果你的能力跳不出那口井,我不可能总是把我自己的能力降低到你的水平来和你对话。我前面的回复不管对错,有论点,有论据,有流程,有解读,反观你的回复,你自己看看多少是可以正常讨论的东西。
再说下去无意义,已经没有技术话题了,你真的不觉得丢脸吗。

连什么是通信都不能回答,还谈什么网络和HTTP。
还是那句话,问题可以讨论,不想讨论就算了,请不要人身攻击,我有什么丢脸的,就算我不耻下问还不行吗?
就冲这点,我还不想和你讨论了。你被误导过,看来还很严重。

行了,别丢人了,我不想回答你,你拿着无知当勇敢,丢人显眼,我可不想和你站一起被大家讨论,你这种人模人样的所谓老师我见多了。我明确告诉过你我从心里恶心你这种误人子弟又没有自知之明的老师!明明自己不会这块,一定要倚老卖老的东拉西扯维护那点社会早已看清楚的所谓专家权威。我说你只针对你一个人你一个人恶心也就罢了,你那乱写的书扔出去就是在水池里下毒。误人子弟这种灭良心的行为你也不怕被人挫脊梁骨。

非常感谢楼主,最近正在学相关方面的知识,遇到一些问题,正好楼主在这里做了详细的分析和说明,给我们提供了一些解决问题的思路和方法,我要向楼主学习,楼主真棒

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top