收藏官网首页
查看: 11427|回复: 29

[技术分享] 8266原生乐鑫SDK高级使用之封装Post与Get请求云端

9

主题

81

帖子

1256

积分

金牌会员

Rank: 6Rank: 6

积分
1256
发表于 2017-11-28 20:10:12 | 显示全部楼层 |阅读模式
汉枫LPB120模块




      8266原生乐鑫SDK高级使用之封装Post与Get请求云端,拿到“天气预报信息”。

       嗨喽各位机智云小伙伴,小徐我又来啦!这次带来的不是Android的App开发教程,带来的是esp8266全新的知识,昨天社区出了个STM32加8266的天气预报的博文,我甚是欣慰,以为是8266直接加OLED显示天气预报,没想到不是呐!个人大失所望, 逛了这么久的度娘,原生的SDK开发8266天气预报少之又少哎呀!
   
       今天就给大家先出个"8266天气预报的原理与获取数据博文",暂不进一步剖析数据与显示到 OLED。如果有兴趣的,可以私聊我!我们一起搞!哈哈~~

                                          
             <Tips: 本博文理论比较多,所以特意画图进一步给大家说下原理!回复帖子即可下载工程源码!!>      
     
                       
                                                                   机智云发烧友:小徐

                                                                                           2017/11/28

游客,如果您要查看本帖隐藏内容请回复
   




                                                                 目  录
   一、效果演示。

    二、通讯原理。

    三、代码揭示。





   更多8266SDK教程请移步我的GitHub: https://github.com/xuhongv/StudyInEsp8266





  
一、效果演示。

          下图是串口助手返回的天气预报信息,双击打开瞧瞧。





       好吧!我还是复制代码各位看看吧。可能手机党打开不了呢!


  1. GM�X匑IeI旝E爻釩Q@娈]_[窜N臫瀺郹\�%aHP@i薱hFa咤爾@G阝吿TQ征枀H歃E a蹷�aHP@iI塒@娈a繲氣厛TQ睁邊瞃 a蹷�uJQ@i嫂Q@娈q萒陉吺Y蓥迏H鋂膄�a\�� *惣謱滯鮂


  2. ----- PB  start -----  
  3. api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=guangzhou&language=en&unit=c&start=0&days=3
  4. ----- PB next -----  
  5. /v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=guangzhou&language=en&unit=c&start=0&days=3
  6. ----- PB end -----  

  7. ----- PB=true -----  
  8. api.seniverse.com

  9. ----- 请求数据开始-----
  10. GET /v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=guangzhou&language=en&unit=c&start=0&days=3 HTTP/1.1
  11. Content-Type: text/html;charset=utf-8
  12. Accept: */*
  13. Host: api.seniverse.com
  14. Connection: Keep-Alive


  15. -----请求数据结束-----  

  16. 发送数据成功!

  17. ----- 开始接受数据-----

  18. HTTP/1.1 200 OK
  19. Date: Tue, 28 Nov 2017 08:23:45 GMT
  20. Content-Type: application/json; charset=utf-8
  21. Content-Length: 900
  22. Connection: keep-alive
  23. Cache-Control: no-cache
  24. Pragma: no-cache
  25. Expires: -1

  26. {"results":[{"location":{"id":"WS0E9D8WN298","name":"Guangzhou","country":"CN","path":"Guangzhou,Guangzhou,Guangdong,China","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2017-11-28","text_day":"Cloudy","code_day":"4","text_night":"Overcast","code_night":"9","high":"25","low":"18","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"10","wind_scale":"2"},{"date":"2017-11-29","text_day":"Overcast","code_day":"9","text_night":"Light rain","code_night":"13","high":"25","low":"16","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"10","wind_scale":"2"},{"date":"2017-11-30","text_day":"Light rain","code_day":"13","text_night":"Light rain","code_night":"13","high":"21","low":"14","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"10","wind_scale":"2"}],"last_update":"2017-11-28T11:00:00+08:00"}]}

  27. -----结束接受数据-----  

  28.   断开连接成功!
复制代码

     二、通讯原理。(以下的图片均为个人辛苦所绘制,绝对原创!!

           2.1 、 esp8266从联网到云端取数据的原理。




         2.2 、 原理流程大概都懂,但是重要的是我们电子硬件开发者可能不懂什么是post和get请求方式?二者有啥区别?好吧,我再画一个图!!



         2.3 、既然请求方式都懂了,那么我们的8266是怎么做到请求数据呢?好吧!我再再画一个图:

   
三、代码揭示。

    3.1 写头文件 my_http.h”的实现C文件。用于剖析URL,定义post请求或get请求。
  1. #include "my_http.h"
  2. #include "c_types.h"
  3. #include "client.h"

  4. //剖析URL
  5. void ICACHE_FLASH_ATTR http_parse_request_url(char *URL, char *host,char *filename, unsigned short *port) {

  6.     char *PA;
  7.     char *PB;

  8.     memset(host, 0, sizeof(host));
  9.     memset(filename, 0, sizeof(filename));

  10.     *port = 0;

  11.     if (!(*URL)){
  12.         uart0_sendStr("\r\n ----- URL return -----  \r\n");
  13.         return;
  14.     }

  15.     PA = URL;
  16.     if (!strncmp(PA, "http://", strlen("http://"))) {
  17.         PA = URL + strlen("http://");
  18.     } else if (!strncmp(PA, "https://", strlen("https://"))) {
  19.         PA = URL + strlen("https://");
  20.     }

  21.     PB = strchr(PA, '/');
  22.     if (PB) {
  23.         uart0_sendStr("\r\n ----- PB=true -----  \r\n");
  24.         memcpy(host, PA, strlen(PA) - strlen(PB));
  25.         if (PB + 1) {
  26.             memcpy(filename, PB + 1, strlen(PB - 1));
  27.             filename[strlen(PB) - 1] = 0;
  28.         }
  29.         host[strlen(PA) - strlen(PB)] = 0;

  30.         uart0_sendStr(host,strlen(host));

  31.     } else {
  32.         uart0_sendStr("\r\n ----- PB=false -----  \r\n");
  33.         memcpy(host, PA, strlen(PA));
  34.         host[strlen(PA)] = 0;
  35.         uart0_sendStr(host,strlen(host));
  36.     }
  37.     PA = strchr(host, ':');
  38.     if (PA){
  39.         *port = atoi(PA + 1);
  40.     }else{
  41.         *port = 80;
  42.     }
  43. }

  44. //寻找DNS解析,并且配置
  45. void ICACHE_FLASH_ATTR user_esp_dns_found(const char *name, ip_addr_t *ipaddr,void *arg) {

  46.     struct ip_info info;
  47.     wifi_get_ip_info(STATION_IF, &info);
  48.     my_station_init(ipaddr, &info.ip, port);

  49. }

  50. //定义Get请求的实现
  51. void ICACHE_FLASH_ATTR startHttpQuestByGET(char *URL){
  52.     struct ip_addr addr;
  53.     memset(buffer,0,1024);
  54.     http_parse_request_url(URL,host,filename,&port);
  55.     os_sprintf(buffer,GET,filename,host);
  56.     espconn_gethostbyname(&user_tcp_conn,host, &addr,
  57.     user_esp_dns_found);
  58. }


  59. //定义Post请求的实现
  60. void ICACHE_FLASH_ATTR startHttpQuestByPOST(char *URL,char *method,char *postdata){
  61.     struct ip_addr addr;
  62.     memset(buffer,0,1024);
  63.     http_parse_request_url(URL,host,filename,&port);
  64.     os_sprintf(buffer,POST,filename,strlen(postdata),host,postdata);
  65.     espconn_gethostbyname(&user_tcp_conn,host, &addr,
  66.     user_esp_dns_found);
  67. }
复制代码

3.2、写头文件client.h的实现C文件。用于配置本地端口、连接服务器。

  1. #include "client.h"
  2. #include "iconv.h"
  3. #include "stdio.h"
  4. #include "string.h"

  5. //成功接收到服务器返回数据函数
  6. void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg, char *pdata,
  7.         unsigned short len) {
  8.     uart0_sendStr("\r\n ----- 开始接受数据----- \r\n ");
  9.     uart0_tx_buffer(pdata, strlen(pdata));
  10.     uart0_sendStr("\r\n -----结束接受数据-----  \r\n ");

  11. }

  12. //发送数据到服务器成功的回调函数
  13. void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg) {
  14.     uart0_sendStr("发送数据成功!\r\n ");
  15. }

  16. //断开服务器成功的回调函数
  17. void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg) {
  18.     uart0_sendStr("断开连接成功!\r\n ");
  19. }

  20. //连接失败的回调函数,err为错误代码
  21. void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err) {
  22.     uart0_sendStr("连接错误,错误代码为%d\r\n", err);
  23.     espconn_connect((struct espconn *) arg);
  24. }

  25. //成功连接到服务器的回调函数
  26. void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg) {
  27.     struct espconn *pespconn = arg;
  28.     espconn_regist_recvcb(pespconn, user_tcp_recv_cb);
  29.     espconn_regist_sentcb(pespconn, user_tcp_sent_cb);
  30.     espconn_regist_disconcb(pespconn, user_tcp_discon_cb);

  31.     uart0_sendStr("\r\n ----- 请求数据开始----- \r\n");
  32.     uart0_tx_buffer(buffer, strlen(buffer));
  33.     uart0_sendStr("\r\n -----请求数据结束-----  \r\n");

  34.     espconn_sent(pespconn, buffer, strlen(buffer));

  35. }
  36. void ICACHE_FLASH_ATTR my_station_init(struct ip_addr *remote_ip,
  37.         struct ip_addr *local_ip, int remote_port) {
  38.     //配置
  39.     user_tcp_conn.type = ESPCONN_TCP;
  40.     user_tcp_conn.state = ESPCONN_NONE;
  41.     user_tcp_conn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp));
  42.     os_memcpy(user_tcp_conn.proto.tcp->local_ip, local_ip, 4);
  43.     os_memcpy(user_tcp_conn.proto.tcp->remote_ip, remote_ip, 4);
  44.     user_tcp_conn.proto.tcp->local_port = espconn_port();
  45.     user_tcp_conn.proto.tcp->remote_port = remote_port;
  46.     //注册
  47.     espconn_regist_connectcb(&user_tcp_conn, user_tcp_connect_cb);
  48.     espconn_regist_reconcb(&user_tcp_conn, user_tcp_recon_cb);
  49.     //连接服务器
  50.     espconn_connect(&user_tcp_conn);
  51. }
复制代码


3.3 程序入口,user_main.c。
  1. #include "driver/uart.h"
  2. #include "user_main.h"

  3. //连接路由器的定时器
  4. os_timer_t checkTimer_wifistate;

  5. void Check_WifiState(void) {
  6.     uint8 getState;
  7.     getState = wifi_station_get_connect_status();

  8.     //如果状态正确,证明已经成功连接到路由器
  9.     if (getState == STATION_GOT_IP) {

  10.         os_printf("WIFI连接成功!把连接路由器的定时器关闭!");
  11.         os_timer_disarm(&checkTimer_wifistate);
  12.         os_timer_disarm(&connect_timer);

  13.         uint8 status = wifi_station_get_connect_status();
  14.         if (status == STATION_GOT_IP) {
  15.             uart0_sendStr("WIFI连接成功!开始请求数据!");
  16.             startHttpQuestByGET(
  17.                     "https://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=guangzhou&language=en&unit=c&start=0&days=3");
  18.             return;
  19.         }
  20.     }

  21. }


  22. void user_init() {

  23.     uart_init(57600, 57600);
  24.     wifi_set_opmode(0x01); //设置为STATION模式
  25.     struct station_config stationConf;
  26.     os_strcpy(stationConf.ssid, "TP-LINK_AliYun");    //改成你自己的   路由器的用户名
  27.     os_strcpy(stationConf.password, "aliyun_123456"); //改成你自己的   路由器的密码
  28.     wifi_station_set_config(&stationConf); //设置WiFi station接口配置,并保存到 flash
  29.     wifi_station_connect(); //连接路由器

  30.     os_timer_disarm(&checkTimer_wifistate); //取消定时器定时
  31.     os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,
  32.     NULL); //设置定时器回调函数
  33.     os_timer_arm(&checkTimer_wifistate, 500, true); //启动定时器,单位:毫秒500

  34. }

复制代码

附加:关于服务器的选择与怎么看接口使用。

   心知天气免费接口:https://www.seniverse.com/doc#daily




IoT软件平台
1、机智云Adnroid开源框架QQ交流群: 434878850

QQ群目前非常活跃,欢迎大家参与进来,交流,讨论,答疑,解惑~~
2、机智云微信公众号: 机智云 gizwits /   机智云智能宠物屋go-iot
关注机智云Gizwits官方公众号随

0

主题

1

帖子

36

积分

新手上路

Rank: 1

积分
36
发表于 2018-6-5 20:07:32 | 显示全部楼层
徐老师,看不到您精心绘制的原理图啊,求原文,求源码,求指导!

1

主题

6

帖子

197

积分

注册会员

Rank: 2

积分
197
发表于 2018-1-31 10:21:02 | 显示全部楼层
"8266天气预报的原理与获取数据博文,谢谢

0

主题

1

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2020-12-16 21:34:32 | 显示全部楼层
谢谢大佬分享,学习一哈!

4

主题

13

帖子

194

积分

注册会员

Rank: 2

积分
194
发表于 2017-11-29 21:44:59 | 显示全部楼层
汉枫LPB120模块
geiwo 太难了

1

主题

2

帖子

38

积分

新手上路

Rank: 1

积分
38
发表于 2018-2-24 18:39:41 | 显示全部楼层
看一看看一看

1

主题

5

帖子

190

积分

注册会员

Rank: 2

积分
190
发表于 2018-3-6 14:11:04 | 显示全部楼层
感谢楼主分享

0

主题

9

帖子

100

积分

注册会员

Rank: 2

积分
100
发表于 2018-3-14 14:21:39 | 显示全部楼层
教您5分钟接入机智云,实现傻瓜式开发
感谢楼主分享

1

主题

5

帖子

376

积分

中级会员

Rank: 3Rank: 3

积分
376
发表于 2018-5-22 06:10:17 | 显示全部楼层
感谢楼主无私分享

0

主题

1

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2018-7-2 15:26:31 | 显示全部楼层
感谢楼主分享!

0

主题

2

帖子

100

积分

注册会员

Rank: 2

积分
100
发表于 2018-8-12 10:37:22 | 显示全部楼层
免费使用STM32、APP自动代码生成工具
It is very good

0

主题

1

帖子

96

积分

注册会员

Rank: 2

积分
96
发表于 2018-8-16 23:25:03 来自手机 | 显示全部楼层
下源码,认真学习

0

主题

4

帖子

44

积分

新手上路

Rank: 1

积分
44
发表于 2019-2-23 08:27:27 | 显示全部楼层
谢谢大神分享

0

主题

3

帖子

116

积分

注册会员

Rank: 2

积分
116
发表于 2019-4-14 14:17:47 | 显示全部楼层
教您5分钟接入机智云,实现傻瓜式开发

感谢楼主分享

0

主题

5

帖子

128

积分

注册会员

Rank: 2

积分
128
发表于 2019-5-7 11:04:04 | 显示全部楼层
感谢楼主的教程!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

© 2011-2017 Gizwits ( 粤ICP备11090211号 )

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