(二)通过网络获取天气信息

这个项目的最终目的是实现在ARM板上,使用qt+opencv实现人脸识别的考勤系统。上一次完成了打开摄像头代码,这一次我打算在系统中加入通过网络实时获取当地天气情况的功能。

 

  • 使用心知天气的API接口实现(免费)

  • 在这里我选择使用心知天气提供的API接口来完成这次任务。JSON格式。

    心知天气的官网网址

    https://www.seniverse.com

    注册登录后,进入控制台,点击我的API项目

  • 记录好自己的API私钥,这里被和谐了,因为私钥是重要的访问密码,最好不要透露出去。

    因为是免费用户,所以只有3个API接口可以调用,其他的都不能用,访问频率也被限制到400次/小时,或者20次/分钟。(当然如果你是土豪可以考虑花钱购买)超过了访问频率,服务器将会拒绝你的访问,直到一个小时后再恢复。

    然后点击产品文档查看API格式

  • 点击天气现象代码说明这里,下载官方提供的图标,程序中会用到。至于使用哪个图标就看你自己喜好了。

  • 接下来看API调用格式,因为是免费用户,可以使用的三个API分别是天气实况,逐日天气和生活指数。

  • 第一个,天气实况

  • 将这个url地址复制下来,将key=后面的打码部分改为自己的私钥,location=后面的beijing改为ip,其他的不用改。ip的意思是自动根据IP地址定位城市,如果想查询指定的城市,可以通过上面的“接口中的通用参数”了解,这一章对API中的参数设置有详细说明。JSON格式我就不细说了,自己去了解吧。

  • 第二个,逐日天气

  • 把url地址复制下来,参数修改如上。

    第三个,生活指数

  • url地址复制下来。

    API接口记录完毕,接下里开始写代码。

  • Qt重点代码解析

    • 访问API接口,并获取返回的JSON数据

    • 访问网址用到了QT的两个类,QNetworkAccessManager和QNetworkReply

      记得包含头文件和在.pro文件中加入network

    • #include <QtNetwork>
      #include <QtNetwork/QNetworkAccessManager>
      #include <QtNetwork/QNetworkRequest>
      #include <QtNetwork/QNetworkReply>

    • 在.h文件中声明变量,因为有三个地址,我想同时访问,所以每一个都要创建对应的QNetworkAccessManager和QNetworkReply

    • QNetworkAccessManager *m_NetManger_now;
      QNetworkAccessManager *m_NetManger_daily;
      QNetworkAccessManager *m_NetManger_life;
      
      QNetworkReply *m_Reply_now;
      QNetworkReply *m_Reply_daily;
      QNetworkReply *m_Reply_life;
      

      接着声明槽

    • private slots:
          void finishedSlot_now(QNetworkReply*);
          void finishedSlot_daily(QNetworkReply*);
          void finishedSlot_life(QNetworkReply*);
      

      在.c的构造函数中加入

    • url_weather_now = "https://api.seniverse.com/v3/weather/now.json?key=你自己的私钥&location=ip&language=zh-Hans&unit=c";
      url_weather_daily = "https://api.seniverse.com/v3/weather/daily.json?key=你自己的私钥&location=ip&language=zh-Hans&unit=c&start=0&days=5";
      url_weather_life = "https://api.seniverse.com/v3/life/suggestion.json?key=你自己的私钥&location=ip&language=zh-Hans";
      
      m_NetManger_now = new QNetworkAccessManager;
      m_NetManger_daily = new QNetworkAccessManager;
      m_NetManger_life = new QNetworkAccessManager;
      
      connect(m_NetManger_now,&QNetworkAccessManager::finished,this,&WeatherWidget::finishedSlot_now);
      connect(m_NetManger_daily,&QNetworkAccessManager::finished,this,&WeatherWidget::finishedSlot_daily);
      connect(m_NetManger_life,&QNetworkAccessManager::finished,this,&WeatherWidget::finishedSlot_life);
      
      m_Reply_now = m_NetManger_now->get(QNetworkRequest(url_weather_now));
      m_Reply_life = m_NetManger_life->get(QNetworkRequest(url_weather_life));
      m_Reply_daily = m_NetManger_daily->get(QNetworkRequest(url_weather_daily));
      

      接着完成槽函数的编写,这里列举一个例子,其他的可以举一反三。

    • void WeatherWidget::finishedSlot_now(QNetworkReply *)
      {
          m_Reply_now->attribute(QNetworkRequest::HttpStatusCodeAttribute);
          m_Reply_now->attribute(QNetworkRequest::RedirectionTargetAttribute);
      
          if (m_Reply_now->error() == QNetworkReply::NoError)
          {
              QByteArray bytes = m_Reply_now->readAll();
              QString data = QString::fromUtf8(bytes);
              qDebug() << "m_Reply_now: " << data;
          }
          else
          {
              qDebug() << m_Reply_now->errorString();
          }
      
          m_Reply_now->deleteLater();
      }
      

      这时运行程序,可以看到qDebug()出来的东西,就是我们需要的JSON格式数据,但是还没有解析。那么接下来我们就来将这些数据从JSON格式中解析出来。

    • JSON格式的解析

    • QT5版本以后提供了JSON解析的库,我们可以直接通过QT进行调用。

      加入头文件

    • #include <QJsonObject>
      #include <QJsonArray>
      #include <QJsonDocument>
      #include <QJsonValue>

      这里为了方便数据处理,自定义了三个结构体进行管理

    • struct Weather_Now_Data
      {
          QString last_update; //最后一次更新时间
          QString country; //国家
          QString id; //ID号
          QString name; //名字
          QString path; //地点
          QString timezone; //时区
          QString timezone_offset; //时区偏移
          QString code; //天气气象代码
          QString temperature; //温度
          QString text; //天气气象文字
      };
      
      struct Weather_Life_Data
      {
          QString car_washing; //洗车
          QString dressing; //穿衣
          QString flu; //感冒
          QString sport; //运动
          QString travel; //旅游
          QString uv; //紫外线
      };
      
      struct Weather_Daily_Data
      {
          QString date; //返回日期
          QString text_day; //白天天气现象文字
          QString code_day; //白天天气现象代码
          QString text_night; //晚间天气现象文字
          QString code_night; //晚间天气现象代码
          QString high; //当天最高温度
          QString low; //当天最低温度
          QString precip; //降水概率 范围0~100,单位百分比
          QString wind_direction; //风向文字
          QString wind_direction_degree; //风向角度 范围0~360
          QString wind_speed; //风速,单位km/h
          QString wind_scale; //风力等级
      };

      接着在.h文件中定义变量

      struct Weather_Now_Data weather_now;
      struct Weather_Daily_Data weather_daily_1, weather_daily_2, weather_daily_3;
      struct Weather_Life_Data weather_life;
      

      定义三个JSON格式解析函数

    • void json_analysis_now(QByteArray data);   //解析json格式现在天气
      void json_analysis_daliy(QByteArray data); //解析json格式逐日时间
      void json_analysis_life(QByteArray data);  //解析json格式生活指数
      

      解析JSON格式其实就是分解大括号和数组,下面我提供天气实况的解析代码,剩下的2个可以举一反三。你可以把我注释掉的qDebug()语句全部取消注释运行一次,然后看看输出结果,自己仔细研究一下就大概知道JSON格式是如何解析的了。

    • void WeatherWidget::json_analysis_now(QByteArray data)
      {
          QByteArray block;
          block = data;
          //qDebug() << "接收 : " << block;
          QJsonParseError json_error;
          QJsonDocument parse_doucment = QJsonDocument::fromJson(block, &json_error);
      
          //qDebug() << "parse_doucment : " << parse_doucment;
          //下面是json格式的解析
          if(json_error.error == QJsonParseError::NoError)
          {
              if(parse_doucment.isObject())
              {
                  //开始解析json对象
                  QJsonObject jsonObject = parse_doucment.object();
                  if(jsonObject.contains("results"))
                  {
                      QJsonValue results_value = jsonObject.take("results");
                      if(results_value.isArray()) //判断他是不是json数组
                      {
                          QJsonArray results_array = results_value.toArray();
                          QJsonObject results_object = results_array.at(0).toObject();
                          //qDebug() << "results_object : " << results_object;
      
                          //提取last_update
                          if(results_object.contains("last_update"))
                          {
                              weather_now.last_update = results_object.take("last_update").toString();
                              //qDebug() << "last_update : " << last_update;
                          }
      
                          //提取location
                          if(results_object.contains("location"))
                          {
                              QJsonValue location_value = results_object.take("location");
                              //qDebug() << "location_value : " << location_value;
                              QJsonObject location_object = location_value.toObject();
                              //提取country
                              if(location_object.contains("country"))
                              {
                                  weather_now.country = location_object.take("country").toString();
                                  //qDebug() << "country : " << country;
                              }
                              //提取id
                              if(location_object.contains("id"))
                              {
                                  weather_now.id = location_object.take("id").toString();
                                  //qDebug() << "id : " << id;
                              }
                              //提取name
                              if(location_object.contains("name"))
                              {
                                  weather_now.name = location_object.take("name").toString();
                                  //qDebug() << "name : " << name;
                              }
                              //提取path
                              if(location_object.contains("path"))
                              {
                                  weather_now.path = location_object.take("path").toString();
                                  //qDebug() << "path : " << path;
                              }
                              //提取timezone
                              if(location_object.contains("timezone"))
                              {
                                  weather_now.timezone = location_object.take("timezone").toString();
                                  //qDebug() << "timezone : " << timezone;
                              }
                              //提取timezone_offset
                              if(location_object.contains("timezone_offset"))
                              {
                                  weather_now.timezone_offset = location_object.take("timezone_offset").toString();
                                  //qDebug() << "timezone_offset : " << timezone_offset;
                              }
      
                          }
      
                          //提取now
                          if(results_object.contains("now"))
                          {
                              QJsonValue now_value = results_object.take("now");
                              //qDebug() << "now_value : " << now_value;
                              QJsonObject now_object = now_value.toObject();
                              //提取code
                              if(now_object.contains("code"))
                              {
                                  weather_now.code = now_object.take("code").toString();
                                  //qDebug() << "code : " << code;
                              }
                              //提取temperature
                              if(now_object.contains("temperature"))
                              {
                                  weather_now.temperature = now_object.take("temperature").toString();
                                  //qDebug() << "temperature : " << temperature;
                              }
                              //提取text
                              if(now_object.contains("text"))
                              {
                                  weather_now.text = now_object.take("text").toString();
                                  //qDebug() << "text : " << text;
                              }
      
                          }
                      }
                  }
              }
          }
      }
      

      将原来的qDebug()打印注释,换成JSON解析函数,然后刷新ui界面上的内容即可。

    • 解析代码有了,下面在槽函数中调用解析函数即可

  • 补充一下

  • 如果在运行qt时报错

那么是qt的openssl库的问题,以下提供解决方案

如果是PC端

在安装目录

QT\MinGW\Tools\QtCreator\bin

找到libeay32.dll和ssleay32.dll链接库

  • 复制到QT\MinGW\5.6\mingw49_32\bin目录下,重新编译程序就可以解决

如果是ubuntu端

在安装目录下是找不到这两个库的,所以要重新编译openssl源码

去openssl的官网下载最新的openssl_1.0.2(似乎需要科学上网,也可以到我的github上下载)最好下载最新的版本,我试过1.0版本,但是并不能解决问题。

https://www.openssl.org/source/

下载好之后,放到ubuntu里,解压

tar –zxvf openssl-1.0.2r.tar.gz
cd openssl-1.0.2r

开始编译

./config enable-shared
make depend
make -j4

然后在当前目录生成4个.so的链接库

将这4个链接库,拷贝到qt的编译库下

/opt/Qt5.6.3/5.6.3/gcc_64/lib

然后重新编译运行程序就可以了

如果是ARM板,那么就需要交叉编译,注意修改交叉工具链,然后把生成的链接库拷贝到ARM板的/usr/lib目录下。

  • 测试

当然要保证板子能连上外网,才能成功获取数据。如图,测试成功。

Qt完整源码放在github上,有需要可以自行下载。 代码名称为190513.zip和190514.zip

https://github.com/ljy980330/opencv_face_sys

说明

190513.zip只有第一个测试图的界面,190514.zip加入了第二个界面的代码,触发方式为点击第一个界面的天气框内部的任意地方,进入第二个界面,在第二个界面点击屏幕任何区域都可以再次回到第一个界面。

下一章,讲解测试图1中右上角的系统信息如何获取。

 

有任何问题可以在下面给我留言!大家一起学习!

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt界面通过网络获取天气信息的过程,一般可以分为以下几个步骤: 第一步,创建请求对象。使用Qt提供的QNetworkRequest类创建一个请求对象,设置请求的URL地址以及请求的Header信息。 第步,发送请求。使用Qt的QNetworkAccessManager类发送上述请求对象,调用其get()函数即可发送请求。 第三步,接收相应。Qt的QNetworkAccessManager类会自动接收到服务器的相应信息,可以通过其finished()信号捕捉到这个事件,回调函数中则可以读取响应的信息。 第四步,解析数据。一般天气信息返回的是Json格式数据,我们需要使用Qt的Json解析器Qt Json来解析数据,将其转换成相应的数据结构,例如用QJsonObject表示城市名、温度、天气状况等信息。 第五步,更新UI。将第四步中解析得到的数据结构,通过Qt界面的QLabel、QTextBrowser等控件,动态地更新显示在界面上。 需要注意在整个网络获取天气信息的过程中,需要添加相应的错误处理,例如网络连接失败、天气数据解析出错等等情况,以保证界面能够及时地响应用户的操作。 ### 回答2: Qt界面是一种基于C++的图形用户界面开发框架。这种框架可以帮助开发者创建出漂亮、易于使用、跨平台的应用程序界面。Qt界面中内置了许多通信和网络相关的类库,使得开发者可以很方便地利用网络进行数据的获取和传输。 获取天气信息通常需要连接到一个天气服务的API,通过发送HTTP请求来获取数据,再将数据解析回传给应用程序进行处理。在Qt界面中,可以使用QNetworkAccessManager等相关类库来实现这个过程。具体而言,可以通过下列步骤来实现: 1. 创建一个QNetworkAccessManager对象,该对象可以用于发送HTTP请求和接收响应数据。 2. 构造HTTP请求对象。对于获取天气信息,通常需要指定一个特定的URL,以及HTTP请求头部的一些参数,例如浏览器类型、语言等。 3. 发送HTTP请求,并等待响应。当响应数据到达时,QNetworkAccessManager对象会发出相应的信号,用于通知应用程序已经得到响应数据。 4. 按照天气API返回的格式,解析响应数据,并提取所需要的信息。这部分工作需要根据具体API的规定进行实现。 5. 将解析获得的天气信息显示在Qt界面上。这一过程中,可以利用Qt的控件和布局等功能,将获取到的信息以适当的方式进行展示。 综上所述,Qt界面通过网络获取天气信息可以利用QNetworkAccessManager等类库,通过发送HTTP请求、解析响应数据实现。这种方法具有可靠性高、代码清晰等优点,可以满足大多数天气API的调用需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值