之前的测评文章,介绍过使用ESP8266和DHT11温湿度传感器来获取室内温湿度,然后通过wifi发送给OK3568板子进行数据展示。
本篇,通过连网进行网络天气的获取,可以得到最近15天的天气信息,先来看下展示效果:
1 天气获取API接口
对于网络天气的获取,这里使用下面这个API接口进行网络天气信息的获取,可以获取到15天的天气信息
根据不同城市对应的城市ID,可以查询全国各个城市的天气信息,城市ID的对照表如下图,比如杭州的城市ID就是10121011
将天气信息获取的地址与城市ID结合起来,即可获取到当前的时间指定城市的天气信息,可以在浏览器中先查看下获取到的天气信息,如下图:
2 JSON解析
获取到的天气是JSON格式的,需要对JSON数据进行解析,从而得到具体的天气、温度等信息。
JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
SON对象是一个无序的"名称/值"键值对的集合:
- 以"
{
“开始,以”}
"结束,允许嵌套使用
- 每个名称和值成对出现,名称和值之间使用"
:
"分隔
- 键值对之间用"
,
"分隔
- 在这些字符前后允许存在无意义的空白符
对于键值,可以有如下值:
- 一个新的json对象
- 数组:使用"
[
“和”]
"表示
- 数字:直接表示,可以是整数,也可以是浮点数
- 字符串:使用引号
"
表示
- 字面值:false、null、true中的一个(必须是小写)
在嵌入式开发中,可以使用cJSON来对JSON数据进行解析。cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。
cJSON使用cJSON结构体来表示一个JSON数据:
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
ch ar *string;
} cJSON;
3 Qt天气界面
主要来看下天气信息的显示:
- drawWeatherInfo 用于上半部分界面中天气信息的显示,包括当前温度,当前的温度范围等
- drawStatusBar 用于上半部分界面中状态栏信息的展示,主要是显示当前是星期几
void WeatherView::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.scale(m_scaleX, m_scaleY);
painter.drawPixmap(0, 0, m_pixmapWeatherBackground);
drawWeatherInfo(&painter);
drawStatusBar(&painter);
}
void WeatherView::drawWeatherInfo(QPainter *painter)
{
painter->save();
foreach (QtPixmapButton *btn, m_btns)
{
QRect rect(btn->rect().left(), btn->rect().top() + m_nYOffset, btn->rect().width(), btn->rect().height());
painter->drawPixmap(rect, btn->pixmap());
}
painter->setPen(QColor("#ffffff"));
QFont font(Skin::m_strAppFontBold);
font.setPixelSize(28);
font.setBold(true);
painter->setFont(font);
if (!m_strErrorMsg.isEmpty())
{
painter->drawText(m_rectCenter, Qt::AlignCenter, m_strErrorMsg);
}
else
{
int nW = getTextWidthByFont(painter->font(), m_strWeatherDatas.at(0));
painter->drawText((m_nBaseWidth - nW) / 2, m_nYOffset + 10, nW, 25, Qt::AlignCenter, m_strWeatherDatas.at(0));
font.setPixelSize(100);
painter->setFont(font);
nW = getTextWidthByFont(painter->font(), m_strWeatherDatas.at(1) + "°");
QRect rectTemp((m_nBaseWidth - nW - 90) / 2, m_nYOffset + 35, nW, 140);
painter->drawText(rectTemp, Qt::AlignCenter, m_strWeatherDatas.at(1) + "°");
QRect rectRight(rectTemp.right() + 10, rectTemp.top() + 25, m_pixmapWeatherType.width(), m_pixmapWeatherType.height());
painter->drawPixmap(rectRight, m_pixmapWeatherType);
font.setPixelSize(24);
painter->setFont(font);
rectRight = QRect(rectRight.left(), rectRight.bottom(), 200, 30);
painter->drawText(rectRight, Qt::AlignVCenter, m_strWeatherDatas.at(3));
rectRight = QRect(rectRight.left(), rectRight.bottom(), 200, 30);
painter->drawText(rectRight, Qt::AlignVCenter, m_strWeatherDatas.at(4));
}
painter->restore();
}
void WeatherView::drawStatusBar(QPainter *painter)
{
painter->save();
QFont font(Skin::m_strAppFontBold);
font.setPixelSize(18);
painter->setFont(font);
painter->setPen(QColor("#797979"));
QString strTemp = tr("预报");
int nW = getTextWidthByFont(painter->font(), strTemp);
painter->drawText(25, this->height() - 25, nW, 25, Qt::AlignCenter, strTemp);
strTemp = tr("今天");
nW = getTextWidthByFont(painter->font(), strTemp);
painter->drawText(m_nBaseWidth - nW - 85, m_nBaseHeight - 25, nW, 25, Qt::AlignCenter, strTemp);
painter->setPen(QColor("#ffffff"));
strTemp = getTodayOfWeek();
nW = getTextWidthByFont(painter->font(), strTemp);
painter->drawText(m_nBaseWidth - 85, m_nBaseHeight - 25, 60, 25, Qt::AlignCenter, strTemp);
painter->restore();
}
对于天气的查询,如下:
WeatherWidget::WeatherWidget(QWidget *parent) : QtAnimationWidget(parent)
{
this->SetBackground(QColor("#014b8a"));
InitWidget();
CityBook::Instance()->LoadConfig(qApp->applicationDirPath() + "/conf/city.json");
m_strCityCode = AppConfig::ReadSetting("Weathcer", "city", "101210101").toString();
m_cityManager = NULL;
m_weatherApi = new WeatherApi(this);
connect(m_weatherApi, SIGNAL(signalResult(QByteArray)), this, SLOT(SltWeatherReply(QByteArray)));
for (int i = 0; i < 7; i++)
{
m_weatherItems.insert(i, new QtListWidgetItem(i,
QString("雷阵雨"),
QString("27°~ %1°").arg(30 + i),
QPixmap(":/images/weather/ic_weath_type.png")));
}
m_weatherReport->SetItems(m_weatherItems);
QTimer::singleShot(500, this, SLOT(InitWeather()));
}
4 测试
在Ubuntu中使用RK3568的编译工具链进行交叉编译,然后将编译文件放到OK3568板子中运行。
运行效果如下,界面下半部分的天气信息,可以左右滑动,查看最近15日的天气。
5 总结
本篇介绍了OK3568开发板通过连网获取网络天气,并通过Qt界面进行展示。