找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3228|回复: 0
收起左侧

HTTP+mini-SD网页上温度的显示

[复制链接]
ID:99624 发表于 2015-12-22 23:59 | 显示全部楼层 |阅读模式
 git一个HTTP sever的代码,移植完毕,修改了一些变量和宏之后编译通过,看了一下效果,基本的网页可以显示,但是他是基于FLASH data的,需要把html文件编译进ROM中,而我不想这样,这样会占用大量的RO-data段。于是乎之前的文件系统用上了,要是让他自动的加载TF卡上的文件和图片就可以解放ROM了,这样的话需要看一下作者的实现框架,然后根据框架对源码进行修改。最后加入文件系统。完成组合。


1、websever 程序框架
就我拿到的源码分析,可以分为这么几部分:
1、accept -TCP 
2、获取HTTP  GET/POST请求,并取得URL。
3、HTTP 分析URL并对HTTP做响应。数据交换
4、文件传输完毕结束。
5、fin -TCP

2、虚拟文件系统
源码没有文件系统,但是作者虚拟了一套简易的文件系统,说白了就是对存在FLASH的HTML文件进行读取管理。虚拟了ROOT根目录,然后在ROOT目录下使用链表连接了几个简单的HTML文件。然后在HTTP请求的时候使用文件open/close。还好做的很接近于比较完整的文件系统。
err = fs_open(&hs->file_handle, g_psDefaultFilenames[loop].name);
uri = g_psDefaultFilenames[loop].name;
for (f =FS_ROOT; f != NULL; f = f->next) {
    if (!strcmp(name, (const char *)f->name)) {
      file->data = (const char *)f->data;
      file->len = f->len;
      file->index = f->len;
      file->pextension = NULL;
      file->http_header_included = f->http_header_included;
 
3、重写
只要看按照他的这个壳子,把内容换成SD卡上的文件就可以完成移植了。
3.1这就需要首先重写这个函数--http_find_file(struct http_state *hs, const char *uri)
#ifdef HTTP_GET_USED_FILE_SYSTEM
/* 使用SD卡上的文件系统执行*/
static err_t
http_find_file(struct http_state *hs, const char *uri)
 if (file_fopen(&Httpfile_CR, &myefs3.myFs, "index.txt", 'r') != 0)
 {
   return 0;
 }
 err=ERR_OK;
       hs->file_handle->data=NULL;//这个不重要了,因为后面要使用READ 读取SD卡 需要改变指针。
      hs->file_handle.len = Httpfile_CR.FileSize;// //写入文件长度相当相当的重要!!!!!!!!!!!!!!!!!!!!!!!!!
      hs->file_handle.index = hs->file_handle.len; //index相同
      hs->file_handle.pextension = NULL; //保持即可
      hs->file_handle.http_header_included = hs->file_handle.http_header_included; //保持即可  
     uri="/index.html";//强制构造或者不该,还让他保持这个名

 3.2这样可以完成文件句柄被指向SD卡中的实际文件-如果有,但是光这样还是不够的,无法把SD卡的文件偏移指针给HTTP自动控制发送。所以这就需要重写另一个函数。
http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) 

#ifdef HTTP_GET_USED_FILE_SYSTEM
static err_t
http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) 
max_len = tcp_sndbuf(pcb);
if(max_len%512!=0) 
{
 max_len=((int)max_len/512)*512; //注意...*512并非废物哦!!!!
}
  HTTPbuf = (char*)mem_malloc((mem_size_t)max_len);
if(HTTPbuf==0)
{
  return ERR_MEM;
}   
  len= file_read(&Httpfile_CR,max_len, (unsigned char*)HTTPbuf);
  ptr= HTTPbuf;//改变文件指针,取得buf的地址。准备发送队列中去
  apiflags=1;//允许copy. 

完成这2步之后就可以完成了HTTP 流了。HTTPSENT会自动的使用TCP的发送队列把数据从SD卡中取出来发送出去了。

4、制作HTLM和logo文件
使用dreamweaver 做一个表格,logo使用PNG图片,可以直接截图一个图片然后另存为放到/logo 文件夹下。起一个名字就好了。(/logo/btlogo.png")完成之后拷贝进SD卡中。程序就可以自动的读取他们了。
把HTML文件拿出来让他和HTTP解析GET的时候的ROOT默认路径文件名一只即可。-index.html(txt)文本也可。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>测试室温度页面</title>
</head>

<body>
<p><img src="http://c.51hei.com/a/a/c/5122215255950875.jpg" width="101" height="79" /></p>
<table width="1219" border="1">
  <tr>
    <th width="404" height="32" bgcolor="#CC0000" scope="col">名称</th>
    <th width="402" bgcolor="#CC0000" scope="col">温度值</th>
    <th width="391" bgcolor="#CC0000" scope="col">时间</th>
  </tr>
  <tr>
    <td height="108" bgcolor="#996666"><div align="center"><strong>DS18B20传感器A</strong></div></td>
    <td bgcolor="#99CC99"><div align="center">xxx.xx<a id="cgqa"></a></div>
    </td>
    <td bgcolor="#CCCC99"><div align="center">
        <!-- #BeginDate format:Ch1m -->15/11/16   19:39<!-- #EndDate -->
    </div></td>
  </tr>
  <tr>
    <td height="128" bgcolor="#996666"><div align="center"><strong>DS18B20传感器B</strong></div></td>
    <td bgcolor="#99CC99"><div align="center">yyy.yy<a id="cgqb"></a></div></td>
    <td bgcolor="#CCCC99"><div align="center">
        <!-- #BeginDate format:Ch1m -->15/11/16   19:39<!-- #EndDate -->
    </div></td>
  </tr>
</table>
<p>&nbsp;</p>
</body>
</html>
logo

 5、温度传感器数据记录到HTML上的方法
温度传感器作为系统的一个任务自动2秒采集一次测试室的温度存入一个固定的缓存中,并且已经完成了ascii转码。只要在实现一个自动找到HTML(txt)文件中的特定的温度显示位置的字符串就可以替换掉原来的字符,这样等HTML再次请求的时候就可以记载上当前的温度数据到网页上了。于是先开始写这个方法。
unsigned int FindFileString(char *str)
{
int len=0,index=0;
char *p;
//  FILE *streamA=(FILE *)&myfile_CR;
do
{
  len = file_read(&myfile_CR,512,(unsigned char*)filebuf);

if(strstr(filebuf,str)!=0)
{
  p= strstr(filebuf,str);
len=(int)p-(int)filebuf;
return len+(index*512);
}
 index++;
}while(len==512);//文件结束????结束必定小于512字节

return 0;//没有找到匹配字符
}

这样一来就可以写出来寻找这个文件中的字符串的函数了提前使用DW中的锚记住ID号。配对这个ID号即可。
#ifdef TEMP_WRITE_HTML  
#include <stdio.h>
#include "file.h"
//温度3位整数+2小数+小数点=6 
#define STRINGLENTH 6
unsigned int FindFileString(char *str);
char filebuf[512];
/*
>xxx.xx<a id="cgqa"></a></div>
>yyy.yy<a id="cgqb"></a></div>
*/
char strA[]="<a name=\"cgqa\"";//匹配字符A 前面的6个字符处就是xxx.xx只要用温度数据替换就好
char strB[]="<a name=\"cgqb\"";//匹配字符B 前面的6个字符处就是yyy.yy只要用温度数据替换就好
char  FS_Writehtml(char *p, unsigned int size) 
static unsigned int deepsizeA=0,deepsizeB=0;//标志字符在文件中的位置
  static char tempt[14]; 
  if((deepsizeB==0)
{
 if (file_fopen(&myfile_CR, &myefs2.myFs, "index.txt", 'r') != 0)
 {
   return 0;
 }
  deepsizeB= FindFileString(strB);//查找A字符和A的位置
   
// write the received data to the file
//datalen = file_write(&myfile_CR,size,p);
file_fread(&myfile_CR,deepsizeB-STRINGLENTH,STRINGLENTH,filebuf);
FileSystemClose(&myfile_CR,&myefs2.myFs);
  }
  if (file_fopen(&myfile_CR, &myefs2.myFs, "index.txt", 'w') != 0)
 {
   return 0;
 }
 file_fwrite(&myfile_CR,deepsizeB-STRINGLENTH,STRINGLENTH,tempt);
 FileSystemClose(&myfile_CR,&myefs2.myFs);

在操作中发现文件系统竟然没有实现'w',只能自己建立一个空文件并填充文件。而不能写拷贝进SD卡的文件,于是还得修改文件系统中的W实现。
源文件为:
case MODE_WRITE:
            if(fs_findFile(fs,filename,&loc,&sec)) /* File may NOT exist, but parent HAS to exist */
{
                 return -2;
} 

最后改成如下这样就OK了
case MODE_WRITE:
            if(fs_findFile(fs,filename,&loc,&sec)==1) /* File may NOT exist, but parent HAS to exist */
{
dir_getFileStructure(fs,&(file->DirEntry), &loc);
                                file_initFile(file,fs,&loc);
file_setAttr(file,FILE_STATUS_OPEN,1);
file_setAttr(file,FILE_STATUS_WRITE,1);
                                 return (0);
} 
 
不知道为什么原作者好像并不想让人使用这个open-W 的函数呢。不 过经过我的测试和比对之后确定是安全的。这个地方真不知道作者他老人家是怎么想的,找了最新的源代码看了一下,同样是这样写的。类似的'r'的实现是这样的,那个接口是被开放出来的 。


 6、页面和抓包分析
网页中的温度就可以显示出来了。
 

HTTP抓包


先是GET请求然后是加载了HTML文件的文本,之后网页会把里面的logo再次使用GET的方法从服务器拿到这张图了。 
TCP包的话每一步都可以看的清的了。












laowang
bt



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表