这里只涉及华为云平台部署以及北向开发。上面链接介绍了如何在旧版的华为云平台进行部署,也有专门的博客介绍新版的华为云平台如何部署。
2 基于QT接入华为OceanConnect云平台
上位机软件与提供的的平台profile是对应的,如果profile的关键参数不一致,需要同步修改软件代码!
2.1 软件介绍
OceanConnect云平台搭建好之后,可以使用模拟器进行发送数据的测试。但是我们必须通过登陆华为OceanConnect云后台,才看到数据,这样其实是不太友好的,因此采用QT平台结合华为发布的API文档来开发一个简单的PC软件。
本次用QT实现与华为OceanConnect云平台(以下简称华为云)的对接,主要包括
1、用户根据appid password登陆
2、自动查询当前应用下所有设备
3、定时向华为云查询最新数据
4、用户可以根据时间段查询云端的历史数据
2.2 效果预览
- 用户需要登录时输入其appId/password(其值为华为OceanConnect云平台配置)中邮件中的“应用对接信息"按钮。
- 登录之后,点击“查询设备”,如果有设备,在下拉框中选择,需要查阅的设备,注意这里显示的为设备名。
- 设置更新周期,该周期指的是,软件定时向云端获取数据的周期。默认是5秒请求一次
- 可以根据时间段,查询数据
3 登陆云平台预备知识
待解决的问题
问题:用户联网登录
1.提供登录界面(客户端),输入用户名和密码;
2.将用户名和密码发送给服务器端,并进行相关查询,如果用户合法,返回用户信息;
3.对返回的用户信息进行解析。
假设:
已经有了服务器和存储着用户名和密码数据库。服务器当接收到客服端的请求的时候,先在数据库中进行查询操作,然后返回用户信息。所以要实现的只是客户端请求信息的配置和对返回信息的解析。
涉及的知识点
网络请求的基础知识
Json
需要解决的技术问题:
在qt中如何设置网络请求
在qt中如何生成和解析Json数据
3.1 Qt中与网络请求相关类介绍
QNetworkAccessManager
Allows the application to send network requests and receive replies
QNetworkRequest
Holds a request to be sent with QNetworkAccessManager
QNetworkReply
Contains the data and headers for a request sent with QNetworkAccessManager
QNetworkRequest设置网络请求的各个参数
QNetworkReply用于接收服务器返回的数据
QNetworkAccessManager充当着一个中介的作用,设置post、get等方式将request发出去,然后监测服务器是否返回数据(存在QNetworkReply中),并将返回得来的reply委托给一个slot处理。
当进行网络请求的时候,要做的事情:
- 生成QNetworkRequest对象,设置请求头、请求所用API所需实参、url等信息;
- 准备解析处理QNetworkReply的slot;
- 生成QNetworkAccessManager,发送request,并将返回来的reply委托给该slot处理(实现上就是一条connect语句)
3.2 QJson的生成与解析
JSON简介
JSON:JavaScript 对象表示法(JavaScript Object Notation)。
JSON 是存储和交换文本信息的语法。类似 XML。
JSON 比 xml 更小、更快,更易解析。
{
"employees": [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName":"Carter" }
]
}
employee 对象是包含 3 个员工记录(对象)的数组
什么是 JSON ?
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
JSON 语法规则
JSON 语法是 JavaScript 对象表示法语法的子集。
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON 名称/值对
JSON 数据的书写格式是:名称/值对。
名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:
"firstName" : "John"
这很容易理解,等价于这条 JavaScript 语句:
firstName = "John"
JSON 值
JSON 值可以是:
- 数字(整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组(在方括号中)
- 对象(在花括号中)
- null
JSON 对象
JSON 对象在花括号中书写:
对象可以包含多个名称/值对:
{ "firstName":"John" , "lastName":"Doe" }
这一点也容易理解,与这条 JavaScript 语句等价:
firstName = "John"
lastName = "Doe"
JSON 数组
JSON 数组在方括号中书写:
数组可包含多个对象:
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
对象 "employees" 是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。
JSON 使用 JavaScript 语法
因为 JSON 使用 JavaScript 语法,所以无需额外的软件就能处理 JavaScript 中的 JSON。
通过 JavaScript,您可以创建一个对象数组,并像这样进行赋值:
例子
var employees = [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName": "Carter" }
];
可以像这样访问 JavaScript 对象数组中的第一项:
employees[0].lastName;
返回的内容是:
Gates
可以像这样修改数据:
employees[0].lastName = "Jobs";
JSON 文件
- JSON 文件的文件类型是 ".json"
- JSON 文本的 MIME 类型是 "application/json"
无论是设置request所需的参数信息,还是返回来的reply,其数据均采用QJson的形式表示,所以要实现网络请求,QJson的生成和解析重要。
Qt中与JSON相关类介绍
QJsonDocument 类提供了读写JSON文档的方式, JSON文档 可以从它的基于文本的表示 使用QJsonDocument::fromJson()转换为QJsonDocument,用.toJSON()将其转换回文字。
QJsonArray封装了JSON中的数组。
QJsonObject封装了JSON中的对象。
QJsonValue封装了JSON中的值。
QJsonParseError 用于报告JSON解析中的错误类型。
基于QJsonObject的Json生成与解析
1.生成json
QJsonObject json;
json.insert("name", QString("Qt"));
json.insert("version", 5);
json.insert("windows", true);
QJsonDocument document;
document.setObject(json);
QByteArray byte_array = document.toJson(QJsonDocument::Compact);
QString json_str(byte_array);
结果
json_str为: {"name": "Qt","version": 5,"windows": true}
2.解析Json
QJsonParseError json_error;
QJsonDocument parse_doucment = QJsonDocument::fromJson(byte_array, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
if(parse_doucment.isObject())
{
QJsonObject obj = parse_doucment.object();
if(obj.contains("name"))
{
QJsonValue name_value = obj.take("name");
if(name_value.isString())
{
QString name = name_value.toString();
}
}
if(obj.contains("version"))
{
QJsonValue version_value = obj.take("version");
if(version_value.isDouble())
{
int version = version_value.toVariant().toInt();
}
}
if(obj.contains("windows"))
{
QJsonValue version_value = obj.take("windows");
if(version_value.isBool())
{
bool flag = version_value.toBool();
}
}
}
}
结果:
name:Qt
version:5
windows:true
基于QJsonArray的的Json生成与解析
1.生成json
QJsonArray json;
json.insert(0, QString("Qt"));
json.insert(1, QString("version"));
json.insert(2, true);
QJsonDocument document;
document.setArray(json);
QByteArray byte_array = document.toJson(QJsonDocument::Compact);
QString json_str(byte_array);
结果
json_str:["Qt","version",true]
2.解析json
QJsonParseError json_error;
QJsonDocument parse_doucment = QJsonDocument::fromJson(byte_array, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
if(parse_doucment.isArray())
{
QJsonArray array = parse_doucment.array();
int size = array.size();
for(int i=0; i<size; i++)
{
QJsonValue value = array.at(i);
if(value.isString())
{
QString name = value.toString();
}
else if(value.isBool())
{
bool flag = value.toBool();
}
}
}
}
结果
数组不同下标对应的值
0:Qt
1:version
2:true
4.login.h / login.cpp / login.ui
login.ui
四个标签,四个文本框,两个按钮
login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QDialog>
#include <QFile>
#include <QByteArray>
#include <QString>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QDebug>
namespace Ui {
class login;
}
class login : public QDialog
{
Q_OBJECT
public:
explicit login(QWidget *parent = nullptr);
~login();
private slots:
//登陆
void on_pushButton_login_clicked();
//载入
void on_pushButton_clicked();
//当鉴权成功后会发送给登陆一个信号,然后再登陆中,绑定此信号到onSignLogin槽函数
void onSignLogin(int codeNum);
private:
Ui::login *ui;
};
#endif // LOGIN_H
login.cpp
#include "login.h"
#include "ui_login.h"
#include "datacomponent.h"
extern DataComponent g_DC;
login::login(QWidget *parent) :
QDialog(parent),
ui(new Ui::login)
{
ui->setupUi(this);
connect(&g_DC, SIGNAL(signMsgToLogin(int)), this, SLOT(onSignLogin(int)));
}
login::~login()
{
delete ui;
}
//载入文件
void login::on_pushButton_clicked()
{
QFile file;
QByteArray configData;