增加一些异常提示。

This commit is contained in:
luocai 2024-08-22 10:48:28 +08:00
parent 0c823a85b3
commit 7e28896159
10 changed files with 167 additions and 49 deletions

View File

@ -139,11 +139,12 @@ void Application::updateShieldedAreaPoints(const QList<QPointF> &points) {
}
}
void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask,
const QString &gateway) {
void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway,
const QString &dns) {
if (!m_device.expired()) {
auto device = m_device.lock();
device->updateNetworkInfomation(dhcp, ip, netmask, gateway);
device->updateNetworkInfomation(dhcp, ip, netmask, gateway, dns);
emit newMessage(1, "网络设置", "设置成功,请重新搜索并连接设备!");
}
}
@ -158,11 +159,15 @@ void Application::connectToDevice(int index) {
disconnect(device.get(), &DeviceConnection::firmwareChanged, this, &Application::onDeviceFirmware);
disconnect(device.get(), &DeviceConnection::otaProgressChanged, this,
&Application::currentDeviceOtaProgressChanged);
disconnect(device.get(), &DeviceConnection::connected, this, &Application::onDeviceConnected);
disconnect(device.get(), &DeviceConnection::disconnected, this, &Application::onDeviceDisconnected);
device->setH264FrameCallback(DeviceConnection::H264FrameCallback());
device->setLiveStreamEnabled(false);
if (!m_currentFirmware.isEmpty()) {
m_currentFirmware.clear();
}
m_currentDeviceConnected = false;
}
if (index >= 0) {
auto device = m_devices->device(index);
@ -176,6 +181,8 @@ void Application::connectToDevice(int index) {
connect(device.get(), &DeviceConnection::firmwareChanged, this, &Application::onDeviceFirmware);
connect(device.get(), &DeviceConnection::otaProgressChanged, this,
&Application::currentDeviceOtaProgressChanged);
connect(device.get(), &DeviceConnection::connected, this, &Application::onDeviceConnected);
connect(device.get(), &DeviceConnection::disconnected, this, &Application::onDeviceDisconnected);
device->setH264FrameCallback([this](const char *data, uint32_t size) {
auto image = m_player->decode((const uint8_t *)data, size);
if (image) {
@ -193,6 +200,7 @@ void Application::connectToDevice(int index) {
m_currentAntiClipAreaPoints = area.antiClipArea;
m_currentNetworkInfomation = device->networkInfomation();
m_currentFirmware = device->infomation().firmwareVersion;
m_currentDeviceConnected = device->isConnected();
emit currentOpenDoorAreaPointsChanged();
emit currentShieldedAreaPointsChanged();
emit currentAntiClipAreaPointsChanged();
@ -202,6 +210,7 @@ void Application::connectToDevice(int index) {
emit currentNetworkInfomationChanged();
}
emit currentFirmwareChanged();
emit currentDeviceConnectedChanged();
}
void Application::startSearchDevice() {
@ -212,7 +221,11 @@ void Application::startSearchDevice() {
void Application::upgradeDevice(const QString &file) {
if (!m_device.expired()) {
auto device = m_device.lock();
if (device->isConnected()) {
device->requestOta(file);
} else {
emit newMessage(2, "OTA升级", "设备已离线,请重新连接设备!");
}
}
}
@ -243,6 +256,17 @@ void Application::onDeviceFirmware(const QString &firmware) {
}
}
void Application::onDeviceConnected() {
m_currentDeviceConnected = true;
emit currentDeviceConnectedChanged();
}
void Application::onDeviceDisconnected() {
m_currentDeviceConnected = false;
emit currentDeviceConnectedChanged();
m_collector->stop();
}
int Application::exec() {
QQmlApplicationEngine engine;
engine.addImageProvider("videoframe", m_videoFrameProvider);

View File

@ -38,6 +38,7 @@ class Application : public QObject {
Q_PROPERTY(
NetworkInfomation currentNetworkInfomation READ currentNetworkInfomation NOTIFY currentNetworkInfomationChanged)
Q_PROPERTY(QString currentFirmware MEMBER m_currentFirmware NOTIFY currentFirmwareChanged)
Q_PROPERTY(bool currentDeviceConnected MEMBER m_currentDeviceConnected NOTIFY currentDeviceConnectedChanged)
friend class Amass::Singleton<Application>;
public:
@ -66,7 +67,7 @@ public:
Q_INVOKABLE void updateAntiClipAreaPoints(const QList<QPointF> &points);
Q_INVOKABLE void updateShieldedAreaPoints(const QList<QPointF> &points);
Q_INVOKABLE void updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask,
const QString &gateway);
const QString &gateway, const QString &dns);
Q_INVOKABLE void connectToDevice(int index);
Q_INVOKABLE void upgradeDevice(const QString &file);
Q_INVOKABLE void startSearchDevice();
@ -84,7 +85,9 @@ signals:
void currentAntiClipAreaEnabledChanged();
void currentNetworkInfomationChanged();
void currentFirmwareChanged();
void currentDeviceConnectedChanged();
void currentDeviceOtaProgressChanged(bool status, int progress, const QString &message);
void newMessage(int type, const QString &title, const QString &message);
protected:
Application(int &argc, char **argv);
@ -93,6 +96,8 @@ protected:
void onDeviceAntiClipArea(bool enabled, const QList<QPointF> &points);
void onDeviceNetworkInfomation(const NetworkInfomation &info);
void onDeviceFirmware(const QString &firmware);
void onDeviceConnected();
void onDeviceDisconnected();
private:
std::shared_ptr<QGuiApplication> m_app;
@ -110,6 +115,7 @@ private:
QList<QPointF> m_currentAntiClipAreaPoints;
NetworkInfomation m_currentNetworkInfomation;
QString m_currentFirmware;
bool m_currentDeviceConnected = false;
};
#endif // APPLICATION_H

View File

@ -11,11 +11,13 @@ struct NetworkInfomation {
Q_PROPERTY(QString ip MEMBER ip)
Q_PROPERTY(QString netmask MEMBER netmask)
Q_PROPERTY(QString gateway MEMBER gateway)
Q_PROPERTY(QString dns MEMBER dns)
public:
bool dhcp;
QString ip;
QString netmask;
QString gateway;
QString dns;
};
Q_DECLARE_METATYPE(NetworkInfomation)

View File

@ -83,7 +83,7 @@ void DeviceConnection::requestOpenDoorArea() {
m_requests.push(task);
}
void DeviceConnection::updateOpenDoorAreaPoints(AreaWay way, const QList<QPointF> &points) {
QFuture<bool> DeviceConnection::updateOpenDoorAreaPoints(AreaWay way, const QList<QPointF> &points) {
Task task;
task.command = "a03opendoor1_setdata";
task.task = [this, way, points]() {
@ -110,12 +110,14 @@ void DeviceConnection::updateOpenDoorAreaPoints(AreaWay way, const QList<QPointF
auto text = boost::json::serialize(request);
m_commandSocket->write(text.data(), text.size());
LOG(info) << "updateOpenDoorAreaPoints";
};
task.future = std::make_shared<QFutureInterface<bool>>();
if (m_requests.empty()) {
task.task();
}
auto ret = task.future->future();
m_requests.push(task);
return ret;
}
void DeviceConnection::requestShieldedArea() {
@ -269,11 +271,11 @@ void DeviceConnection::requestNetworkInfomation() {
m_requests.push(task);
}
void DeviceConnection::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask,
const QString &gateway) {
QFuture<bool> DeviceConnection::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask,
const QString &gateway, const QString &dns) {
Task task;
task.command = "netconfig_setdata";
task.task = [this, dhcp, ip, netmask, gateway]() {
task.task = [this, dhcp, ip, netmask, gateway, dns]() {
boost::json::object request;
request["func"] = "netconfig_setdata";
request["deviceid"] = "0";
@ -282,16 +284,20 @@ void DeviceConnection::updateNetworkInfomation(bool dhcp, const QString &ip, con
data["ip"] = ip.toStdString();
data["netmask"] = netmask.toStdString();
data["gateway"] = gateway.toStdString();
data["dns"] = dns.toStdString();
request["data"] = std::move(data);
auto text = boost::json::serialize(request);
m_commandSocket->write(text.data(), text.size());
LOG(info) << "requestUpdateNetworkInfomation";
};
task.future = std::make_shared<QFutureInterface<bool>>();
if (m_requests.empty()) {
task.task();
}
auto ret = task.future->future();
m_requests.push(task);
return ret;
}
void DeviceConnection::requestOta(const QString &file) {
@ -359,7 +365,7 @@ void DeviceConnection::transferBinContent() {
m_sendedSize += sendSize;
auto fileProgress = static_cast<float>(m_sendedSize) / m_uploadBuffer.size();
m_otaProgress = 2 + 95 * fileProgress;
m_otaProgress = 2 + 96 * fileProgress;
emit otaProgressChanged(true, m_otaProgress, "向设备发送OTA升级文件......");
if (m_sendedSize < m_uploadBuffer.size()) {
@ -381,7 +387,7 @@ void DeviceConnection::transferBinContent() {
}
}
QString DeviceConnection::handleCommand(const std::string_view &replyText) {
QString DeviceConnection::handleCommand(const std::string_view &replyText, const Task *task) {
QString ret;
boost::system::error_code error;
auto replyValue = boost::json::parse(replyText, error);
@ -448,7 +454,11 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText) {
m_networkInfomation.ip = data.at("ip").as_string().c_str();
m_networkInfomation.gateway = data.at("gateway").as_string().c_str();
m_networkInfomation.netmask = data.at("netmask").as_string().c_str();
if (data.contains("dns")) {
m_networkInfomation.dns = data.at("dns").as_string().c_str();
}
emit networkInfomationChanged(m_networkInfomation);
LOG(info) << replyText;
} else if (function == "a15devicedetail_getdata") {
auto &data = reply.at("data").as_object();
auto firmware = QString::fromStdString(std::string(data.at("linux04_firmware").as_string()));
@ -461,7 +471,27 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText) {
} else if (function == "a03opendoor4_setdata") {
requestShieldedArea();
} else if (function == "a03opendoor1_setdata") {
if ((task != nullptr) && (task->command.toStdString() == function)) {
if (task->timeoutTimer) {
task->timeoutTimer->stop();
}
bool status = true;
if (task->future) {
task->future->reportFinished(&status);
}
}
requestOpenDoorArea();
} else if (function == "netconfig_setdata") {
if ((task != nullptr) && (task->command.toStdString() == function)) {
if (task->timeoutTimer) {
task->timeoutTimer->stop();
}
bool status = true;
if (task->future) {
task->future->reportFinished(&status);
}
}
LOG(info) << replyText;
} else if (function == "a22devicefirmware_setdata") {
LOG(warning) << "ota reply: " << replyText;
auto &data = reply.at("data").as_object();
@ -472,18 +502,33 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText) {
QTimer::singleShot(0, this, [this]() { transferBinContent(); });
} else if (value == "2") {
LOG(info) << "md5 check finished";
m_otaProgress = 98;
m_otaProgress = 99;
emit otaProgressChanged(true, m_otaProgress, "设备正在升级中,请稍后......");
QTimer::singleShot(0, this, [this]() {
m_commandSocket->close();
m_h264Socket->close();
if (m_otaTimer == nullptr) {
m_otaTimer = new QTimer(this);
m_otaTimer->setSingleShot(true);
}
m_otaTimer->callOnTimeout(
this,
[this]() {
emit otaProgressChanged(false, m_otaProgress, "升级超时,请检查设备并重新尝试...");
m_otaProgress = -1;
m_commandSocket->close();
m_h264Socket->close();
},
Qt::SingleShotConnection);
m_otaTimer->start(120 * 1000);
});
QTimer::singleShot(25000, this, [this]() {
LOG(info) << "try connect after ota.";
m_commandSocket->connectToHost(m_infomation.ip, 8000);
m_h264Socket->connectToHost(m_infomation.ip, 8000);
m_needReconnect = true;
});
} else {
emit otaProgressChanged(false, m_otaProgress, QString("升级失败,错误码: %1").arg(value.c_str()));
}
} else {
LOG(warning) << "unknown reply: " << replyText;
@ -501,12 +546,15 @@ void DeviceConnection::onConnected() {
requestNetworkInfomation();
emit connected();
m_timerId = startTimer(2500);
if (m_otaProgress > 0) {
m_otaProgress = 100;
emit otaProgressChanged(true, m_otaProgress, "设备升级成功!");
if (m_otaProgress == 99) {
m_otaProgress = -1;
emit otaProgressChanged(true, 100, "设备升级成功!");
}
if (m_otaTimer != nullptr) {
m_otaTimer->stop();
}
} else if (socket == m_h264Socket) {
if (m_needReconnect) {
if (m_otaProgress >= 99) {
setLiveStreamEnabled(true);
}
}
@ -520,6 +568,10 @@ void DeviceConnection::onDisconnected() {
m_timerId = -1;
}
emit disconnected();
if ((m_otaProgress >= 0) && (m_otaProgress <= 98)) {
m_otaProgress = -1;
emit otaProgressChanged(false, m_otaProgress, "网络断开,设备升级失败!");
}
}
}
@ -555,7 +607,8 @@ void DeviceConnection::onCommandReadyRead() {
while (!m_commandBuffer.isEmpty()) {
auto packageSize = ntohl(*reinterpret_cast<uint32_t *>(m_commandBuffer.data()));
if (m_commandBuffer.size() < (packageSize + sizeof(uint32_t))) break;
auto command = handleCommand(std::string_view(m_commandBuffer.data() + sizeof(uint32_t), packageSize));
auto command = handleCommand(std::string_view(m_commandBuffer.data() + sizeof(uint32_t), packageSize),
m_requests.empty() ? nullptr : &m_requests.front());
m_commandBuffer.remove(0, packageSize + sizeof(uint32_t));
if (!m_requests.empty()) {
@ -573,7 +626,7 @@ void DeviceConnection::onCommandReadyRead() {
void DeviceConnection::onErrorOccurred(QAbstractSocket::SocketError socketError) {
auto socket = dynamic_cast<QTcpSocket *>(sender());
qDebug() << "DeviceConnection::onErrorOccurred" << socketError;
if (m_needReconnect) {
if (m_otaProgress == 99) { // 99 表示设备正在OTA重启需要重连
if (socket->state() == QTcpSocket::UnconnectedState) {
LOG(info) << "try reconnect after ota.";
socket->connectToHost(m_infomation.ip, 8000);

View File

@ -2,6 +2,8 @@
#define DEVICECONNECTION_H
#include "DataStructure.h"
#include <QFuture>
#include <QFutureInterface>
#include <QObject>
#include <QQmlEngine>
#include <QTcpSocket>
@ -59,22 +61,23 @@ public:
Area area() const;
void requestOpenDoorArea();
void updateOpenDoorAreaPoints(AreaWay way, const QList<QPointF> &points);
QFuture<bool> updateOpenDoorAreaPoints(AreaWay way, const QList<QPointF> &points);
void requestShieldedArea();
void updateShieldedAreaPoints(bool enabled, const QList<QPointF> &points);
void requestAntiClipArea();
void updateAntiClipAreaPoints(bool enabled, const QList<QPointF> &points);
void requestResolution(Resolution resolution);
void requestNetworkInfomation();
void updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway);
QFuture<bool> updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway,
const QString &dns);
void requestVersion();
/**
* @brief OTA,
* 1. OTA请求 1
* 2. 2-97
* 3. 98
* 4. 99
* 2. 2-98
* 3. 99
* 4. 100
*
* @param file
*/
@ -91,11 +94,18 @@ signals:
void otaProgressChanged(bool status, int progress, const QString &message);
protected:
class Task {
public:
QString command;
std::function<void()> task;
std::shared_ptr<QTimer> timeoutTimer = nullptr;
std::shared_ptr<QFutureInterface<bool>> future;
};
void onConnected();
void onDisconnected();
void onH264ReadyRead();
void onCommandReadyRead();
QString handleCommand(const std::string_view &replyText);
QString handleCommand(const std::string_view &replyText, const Task *task);
void onErrorOccurred(QAbstractSocket::SocketError socketError);
void timerEvent(QTimerEvent *event) final;
void transferBinContent();
@ -110,17 +120,12 @@ private:
QByteArray m_commandBuffer;
QByteArray m_h264Buffer;
int m_otaProgress = 0;
bool m_needReconnect = false;
int m_otaProgress = -1;
std::vector<uint8_t> m_uploadBuffer;
int m_sendedSize = 0;
QTimer *m_otaTimer = nullptr; // 检测OTA超时
H264FrameCallback m_frameCallback;
class Task {
public:
QString command;
std::function<void()> task;
};
std::queue<Task> m_requests;
int m_timerId = -1;
int heartbeats = 0;

View File

@ -12,11 +12,15 @@ Column {
id: input
onTextChanged: {
valid = validateIp(text);
if(!valid){
hint.text="参数配置无效"
if(text.length<=0){
hint.text = "参数不能为空"
return
}
valid = validateIp(text)
if (!valid) {
hint.text = "参数配置无效"
} else {
hint.text=""
hint.text = ""
}
}
}
@ -28,7 +32,10 @@ Column {
function validateIp(ip) {
// Regular expression for validating IP address
var regex = /^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
return regex.test(ip);
var regex = /^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/
return regex.test(ip)
}
function reset() {
hint.text = ""
}
}

View File

@ -95,7 +95,7 @@ ApplicationWindow {
anchors.bottom: parent.bottom
anchors.left: deviceList.right
anchors.right: parent.right
enabled: deviceList.currentIndex >= 0
enabled: App.currentDeviceConnected&&(deviceList.currentIndex >= 0)
openDoorAreaWay: App.currentOpenDoorAreaWay
openDoorAreaPoints: App.currentOpenDoorAreaPoints
shieldedAreaEnabled: App.currentShieldedAreaEnabled
@ -134,6 +134,9 @@ ApplicationWindow {
if (deviceList.currentIndex < 0) {
showMessageDialog(2, "数据采集", "请先选择设备")
return
} else if(!App.currentDeviceConnected){
showMessageDialog(2, "数据采集", "设备已离线,请重新连接设备!")
return
}
if (App.collector.path.length <= 0) {
folderDialog.open()
@ -149,7 +152,10 @@ ApplicationWindow {
text: "升级"
onClicked: {
if (deviceList.currentIndex < 0) {
showMessageDialog(2, "OTA升级", "请选选择设备")
showMessageDialog(2, "OTA升级", "请先选择设备!")
return
}else if(!App.currentDeviceConnected){
showMessageDialog(2, "OTA升级", "设备已离线,请重新连接设备!")
return
}
otaPopup.open()
@ -171,4 +177,10 @@ ApplicationWindow {
dialog.open()
}
}
Connections {
target: App
function onNewMessage(type, title, message) {
showMessageDialog(type, title, message)
}
}
}

View File

@ -102,7 +102,7 @@ Dialog {
} else if (type === MessageDialog.Type.Warning) {
image.source = "qrc:/qt/qml/AntiClipSettings/resources/warning.svg"
} else if(type === MessageDialog.Type.Failed){
// image.source = "qrc:/AntiClipSettings/resources/prompt_delete.svg"
image.source = "qrc:/qt/qml/AntiClipSettings/resources/prompt_delete.svg"
}
}
}

View File

@ -33,8 +33,7 @@ Popup {
RadioButton {
id: staticMode
text: "静态IP"
checked: true
// checked: !App.currentNetworkInfomation.dhcp
checked: !App.currentNetworkInfomation.dhcp
}
}
@ -106,7 +105,7 @@ Popup {
id: dnsInput
width: 350
height: inputHeight
text: App.currentNetworkInfomation.gateway
text: App.currentNetworkInfomation.dns
}
}
@ -125,7 +124,7 @@ Popup {
App.updateNetworkInfomation(dhcpMode.checked,
ipInput.text,
netmaskInput.text,
gatewayInput.text)
gatewayInput.text,dnsInput.text)
networkPopup.close()
} else {
showMessageDialog(2, "网络设置", "请输入合法参数地址!")
@ -139,4 +138,10 @@ Popup {
}
}
}
onVisibleChanged: {
ipInput.reset()
netmaskInput.reset()
gatewayInput.reset()
dnsInput.reset()
}
}

View File

@ -107,15 +107,19 @@ Popup {
Connections {
target: App
function onCurrentDeviceOtaProgressChanged (status, progress, message) {
if(progress<0)progress=0
otaFinished = !status || (progress>=100)
progressBar.value = progress
progressText.text = `${progress}%`
if(progress>=100){
otaMessage.text = "OTA升级完成"
otaMessage.color = "green"
}else {
otaMessage.text = message
if(progress>=100){
otaMessage.color = "green"
}
}
}
onVisibleChanged: {
if(!visible){
otaMessage.color = "black"
}
}
}