飞凌嵌入式
直播中

fsdzdzy

10年用户 260经验值
擅长:嵌入式技术 控制/MCU opencv
私信 关注
[技术]

【飞凌RK3568开发板试用体验】19-网络天气信息

之前的测评文章,介绍过使用ESP8266和DHT11温湿度传感器来获取室内温湿度,然后通过wifi发送给OK3568板子进行数据展示。

本篇,通过连网进行网络天气的获取,可以得到最近15天的天气信息,先来看下展示效果:
1.png

1 天气获取API接口

对于网络天气的获取,这里使用下面这个API接口进行网络天气信息的获取,可以获取到15天的天气信息
2.png

根据不同城市对应的城市ID,可以查询全国各个城市的天气信息,城市ID的对照表如下图,比如杭州的城市ID就是10121011
3.png

将天气信息获取的地址与城市ID结合起来,即可获取到当前的时间指定城市的天气信息,可以在浏览器中先查看下获取到的天气信息,如下图:
4.png

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数据:

/* The cJSON structure: */
typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;
​
    /* The type of the item, as above. */
    int type;
​
    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    /* The item's number, if type==cJSON_Number */
    double valuedouble;
​
    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    ch ar *string;
} cJSON;

3 Qt天气界面

1.png

主要来看下天气信息的显示:

  • 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;
    // 天气api查询
    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.png

5 总结

本篇介绍了OK3568开发板通过连网获取网络天气,并通过Qt界面进行展示。

回帖(1)

华仔stm32

2023-1-6 22:07:49
感谢分享
举报

更多回帖

发帖
×
20
完善资料,
赚取积分