关于如何建立一个HTTP的虚拟测试桩的方法如下,通过SoapUI建立一个HTTP测试桩,用来模拟远端HTTP服务器。
ESP8266进入透传的配置:(以串口115200波特率为例)
(1)设置WIFI模式
AT+CWMODE=3 //设置为ap+sta共存
响应OK
(2)重启
AT+RST
重启后我们看到,这里出现乱码,乱码的原因是因为模块刚上电的时候,波特率并不是我们所设置的115200,而是会稍微偏大一点。后面就恢复为115200了。
(3)连接路由器
AT+CWJAP="ssid","password" //传入路由的ssid和password
响应OK
(4)查询设备IP
AT+CIFSR
响应设备的ip地址以及其它
(5)连接服务器(TCP)
AT+CIPSTART="TCP","server ip",server port //传入远端服务器的ip以及端口号
响应:OK
(6)开启ESP8266的透传模式
AT+CIPMODE=1
响应OK
(7)开始透传
AT+CIPSEND
响应: > //从此时开始,串口输入的字符会透传到服务器端
将数据通过HTTP发送到远端服务器:
POST /test/upload/messages HTTP/1.1
Host: 192.168.12.68:8999
Content-Type: application/json
Content-Length:17
cache-control: no-cache
{"text1" : "123"}
其中/test/upload/messages为URL的一部分
Host字段添加服务器IP和端口号,这里的服务器IP是192.168.12.68,端口号是8999
所以URL为:http://192.168.12.68:8999/test/upload/messages
Content-Type字段代表当前要使用数据的格式,这里使用的是application/json
Content-Length字段代表当前json数据的长度,也就是后面{"text1","123"}这串数据的长度。通过下面这个工具可知
当前的数据长度为17:
接下来是一个空格,这个空格一定要有,否则HTTP服务器会解析出错
后面的{"text1":"123"}就是我们要发送的json数据,通过串口调试助手将带http协议的json数据发到http测试服务器:
测试结果没有问题,开始写程序,本例程基于stm32f103zet6野火开发板
首先我们把指令用宏定义对指令进行封装:
#define AT_TEST_OK "AT" //测试wifi是否已经正常上电
#define AT_SET_MODE "AT+CWMODE=%d" //设置模式
#define AT_CONNECT_ROUTER "AT+CWJAP="%s","%s"" //连接路由器
#define AT_CONNECT_SERVER "AT+CIPSTART="%s","%s",%d" //连接服务器
#define AT_SET_CIP_MODE "AT+CIPMODE=1" //设置透传模式
#define AT_ENTER_CIP_MODE "AT+CIPSEND" //进入透传模式
下面用具体的子函数实现Wifi操作接口:
//测试wifi模块是否存在
int Wifi_Test_Exist(void)
{
int Err_Count = 0 ;
//给模块上电
macESP8266_CH_ENABLE();
Delay_ms(1000);
macESP8266_RST_HIGH_LEVEL();
Delay_ms(1000);
while(0 == ESP8266_Cmd(AT_TEST_OK, "OK",NULL, 200)) //检查WIFI模块是否在线
{
printf("未检测到模块....rn");
if(Err_Count > 10)
{
Err_Count = 0 ;
return -1 ;
}
++Err_Count ;
}
Err_Count = 0 ;
return 0 ;
}
//设置wifi模式
int Wifi_Set_Mode(int Mode)
{
int Err_Count = 0 ;
char buffer[20] = {0};
sprintf(buffer,AT_SET_MODE,Mode);
while(0 == ESP8266_Cmd(buffer,"OK",NULL, 200))
{
printf("设置模式失败....rn");
if(Err_Count > 10)
{
Err_Count = 0 ;
return -1 ;
}
++Err_Count ;
}
Err_Count = 0 ;
return 0 ;
}
//连接路由器
int Wifi_Connect_Router(const char *ssid, const char *password)
{
int Err_Count = 0 ;
char buffer[50] = {0};
sprintf(buffer,AT_CONNECT_ROUTER,ssid,password);
while(0 == ESP8266_Cmd(buffer, "OK",NULL, 3000))
{
printf("连接路由器失败,正在尝试重新连接....rn");
if(Err_Count > 5)
{
Err_Count = 0 ;
return -1 ;
}
++Err_Count ;
}
Err_Count = 0 ;
return 0 ;
}
//连接服务器
int Wifi_Connect_Server(const char *tcp_or_udp,const char *server_ip, int port_number)
{
int Err_Count = 0 ;
char buffer[50] = {0};
sprintf(buffer,AT_CONNECT_SERVER,tcp_or_udp,server_ip,port_number);
while(0 == ESP8266_Cmd(buffer, "CONNECT", NULL,3000))
{
printf("连接服务器失败,正在尝试重新连接....rn");
if(Err_Count > 10)
{
Err_Count = 0 ;
return -1 ;
}
++Err_Count ;
}
Err_Count = 0 ;
return 0 ;
}
//设置透传模式
int Wifi_Set_Cip_Mode(void)
{
if(false == ESP8266_UnvarnishSend())
return -1 ;
return 0 ;
}
接下来编写WIFI初始化流程:
int Wifi_Module_Init(const char *ssid, const char *password , const char *server_ip , int port_number)
{
int ret = 0 ;
//wifi模块检查
Wifi_Exist:
//检测wifi模块是否存在
ret = Wifi_Test_Exist();
if(0 != ret)
{
printf("wifi初始化失败,请检查硬件是否连接!rn");
return -1 ;
}
printf("wifi初始化成功!n");
//设置wifi模式
ret = Wifi_Set_Mode(3);
if(0 != ret)
{
printf("wifi设置模式失败rn");
goto Wifi_Exist ;
}
printf("wifi设置ap+sta模式成功!n");
//路由器连接检查
Router_Detect:
ret = Wifi_Connect_Router(ssid,password);
if(0 != ret)
{
printf("wifi连接路由器失败,请检查硬件是否连接或者网络是否正确连接rn");
//wifi断电
macESP8266_CH_DISABLE();
macESP8266_RST_LOW_LEVEL();
goto Wifi_Exist ;
}
printf("wifi连接路由器成功n");
ret = Wifi_Connect_Server("TCP",server_ip,port_number);
if(0 != ret)
{
printf("wifi连接服务器失败,请检查网络连接rn");
goto Router_Detect ;
}
printf("wifi连接服务器成功n");
ret = Wifi_Set_Cip_Mode();
if(0 != ret)
{
printf("进入透传模式失败rn");
goto Wifi_Exist ;
}
printf("进入透传模式成功!n");
return 0 ;
}
由于我们要将数据透传到自己的HTTP服务器,所以要封装一个HTTP头部和HTTP数据,数据在服务端以JSON格式进行接收,了解需求后我们需要定义好头部和数据部分。
JSON数据包的协议格式如下:
devicetype:设备类型
time:日期和时间
idno:设备号
type:当前检测的类型
当数据包发送到服务端后,服务端要回200 OK的字符串给串口,这样才算是数据上传成功。
#define HTTP_HEAD
"POST /api/"DEVICE_TYPE"/messages HTTP/1.1rn"
"Host: 120.78.136.134:9003rn"
"Content-Type: application/jsonrn"
"content-length: %drnrn"
#define HTTP_DATA_UPLOAD_PARA
"{"devicetype":"%s","time":"%s","idno":"%s","type":"%s"}"
这里的content-length是如何计算的呢?其实就是HTTP_DATA_UPLOAD_PARA整体的长度。接下来我们实现一个对头部和数据包封装并且将整个数据上传的函数:
//返回1即发送成功
int Http_NEW_Data_Upload(char *time , char *idno)
{
int ContentLength = 0 ;
char *up_data = NULL ;
char *up_head = NULL ;
char *http_data = NULL ;
int Send_Data_ok_flag = 0 ;
up_data = malloc(150);
if(NULL == up_data)
return -1 ;
up_head = malloc(150);
if(NULL == up_head)
return -2 ;
http_data = malloc(300);
if(NULL == http_data)
return -3 ;
snprintf(up_data, 150, HTTP_DATA_UPLOAD_PARA, DEVICE_TYPE, time, idno, "baozhawu");
ContentLength = strlen(up_data);
snprintf(up_head, 150, HTTP_HEAD, ContentLength);
sprintf(http_data,"%s%s",up_head,up_data);
while(0 == ESP8266_Cmd ( http_data, "HTTP/1.1 200 OK", NULL, 3000 ))
{
Send_Data_ok_flag = 0 ;
break ;
}
Send_Data_ok_flag = 1 ;
free(up_data);
free(up_head);
free(http_data);
return Send_Data_ok_flag ;
}
万事具备,只欠东风,下面就可以调用API来完成工作啦:
int main ( void )
{
int ret = 0 ;
USART_Config (); //初始化串口1
SysTick_Init (); //配置 SysTick 为 1ms 中断一次
ESP8266_Init (); //初始化WiFi模块使用的接口和外设
printf ( "rn野火 WF-ESP8266 WiFi模块测试例程rn" ); //打印测试例程提示信息
WIFI_INIT:
ret = Wifi_Module_Init("7745","1552139769344554",SERVER_IP,SERVER_PORT);
if(0 == ret){
printf("wifi连接成功!rn");
Connect_ok_flag = 1 ;
}
while(1)
{
memset(strEsp8266_Fram_Record .Data_RX_BUF,0,1024);
ret = Http_NEW_Data_Upload("2019-03-19 01:32", "10100217420060");
if(1 != ret)
{
//wifi断电
macESP8266_CH_DISABLE();
macESP8266_RST_LOW_LEVEL();
goto WIFI_INIT ;
}
Delay_ms ( 1000 );
}
}
执行程序:
可以看到串口已经收到了回复。