适配设备的上线策略。
This commit is contained in:
parent
31aa3d86ac
commit
d822dcda76
@ -145,7 +145,7 @@ void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QS
|
||||
if (!m_device.expired()) {
|
||||
auto device = m_device.lock();
|
||||
device->updateNetworkInfomation(dhcp, ip, netmask, gateway, dns);
|
||||
emit newMessage(1, "网络设置", "设置成功,请重新搜索并连接设备!");
|
||||
emit newMessage(1, "网络设置", "设置成功,请等待设备重新上线!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,15 @@ bool DeviceConnection::isConnected() const {
|
||||
}
|
||||
|
||||
void DeviceConnection::connect(const Infomation &infomation) {
|
||||
while (!m_requests.empty()) {
|
||||
m_requests.pop();
|
||||
}
|
||||
if (m_commandSocket != nullptr) {
|
||||
m_commandSocket->deleteLater();
|
||||
}
|
||||
if (m_h264Socket != nullptr) {
|
||||
m_h264Socket->deleteLater();
|
||||
}
|
||||
m_infomation = infomation;
|
||||
m_commandSocket = new QTcpSocket(this);
|
||||
QObject::connect(m_commandSocket, &QTcpSocket::disconnected, this, &DeviceConnection::onDisconnected);
|
||||
@ -54,6 +63,7 @@ NetworkInfomation DeviceConnection::networkInfomation() const {
|
||||
}
|
||||
|
||||
void DeviceConnection::setLiveStreamEnabled(bool enabled) {
|
||||
m_videoEnabled = enabled;
|
||||
boost::json::object request;
|
||||
request["func"] = enabled ? "openlivestream_setdata" : "closelivestream_setdata";
|
||||
request["deviceid"] = "0";
|
||||
@ -365,7 +375,9 @@ void DeviceConnection::transferBinContent() {
|
||||
|
||||
auto fileProgress = static_cast<float>(m_sendedSize) / m_uploadBuffer.size();
|
||||
m_otaProgress = 2 + 96 * fileProgress;
|
||||
emit otaProgressChanged(true, m_otaProgress, "向设备发送OTA升级文件......");
|
||||
emit otaProgressChanged(true, m_otaProgress,
|
||||
m_otaProgress < 98 ? "向设备发送升级固件......"
|
||||
: "升级固件发送完成,等待设备校验升级固件......");
|
||||
|
||||
if (m_sendedSize < m_uploadBuffer.size()) {
|
||||
QTimer::singleShot(0, this, &DeviceConnection::transferBinContent);
|
||||
@ -490,6 +502,7 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const
|
||||
task->future->reportFinished(&status);
|
||||
}
|
||||
}
|
||||
requestNetworkInfomation();
|
||||
LOG(info) << replyText;
|
||||
} else if (function == "a22devicefirmware_setdata") {
|
||||
LOG(warning) << "ota reply: " << replyText;
|
||||
@ -497,14 +510,14 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const
|
||||
auto &value = data.at("value").as_string();
|
||||
if (value == "1") {
|
||||
m_otaProgress = 1;
|
||||
emit otaProgressChanged(true, m_otaProgress, "设备已进入OTA升级状态......");
|
||||
emit otaProgressChanged(true, m_otaProgress, "设备已进入升级状态......");
|
||||
QTimer::singleShot(0, this, [this]() { transferBinContent(); });
|
||||
} else if (value == "2") {
|
||||
LOG(info) << "md5 check finished";
|
||||
m_otaProgress = 99;
|
||||
emit otaProgressChanged(true, m_otaProgress, "设备正在升级中,请稍后......");
|
||||
QTimer::singleShot(0, this, [this]() {
|
||||
m_commandSocket->close();
|
||||
m_commandSocket->close(); // 等待设备重新上线后,发起广播。由搜索服务触发重连
|
||||
m_h264Socket->close();
|
||||
if (m_otaTimer == nullptr) {
|
||||
m_otaTimer = new QTimer(this);
|
||||
@ -521,11 +534,6 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const
|
||||
Qt::SingleShotConnection);
|
||||
m_otaTimer->start(60 * 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);
|
||||
});
|
||||
} else {
|
||||
const char *message = nullptr;
|
||||
if (value == "3") {
|
||||
@ -569,7 +577,7 @@ void DeviceConnection::onConnected() {
|
||||
m_otaTimer->stop();
|
||||
}
|
||||
} else if (socket == m_h264Socket) {
|
||||
if (m_otaProgress >= 99) {
|
||||
if (m_videoEnabled) {
|
||||
setLiveStreamEnabled(true);
|
||||
}
|
||||
}
|
||||
@ -640,13 +648,7 @@ void DeviceConnection::onCommandReadyRead() {
|
||||
|
||||
void DeviceConnection::onErrorOccurred(QAbstractSocket::SocketError socketError) {
|
||||
auto socket = dynamic_cast<QTcpSocket *>(sender());
|
||||
qDebug() << "DeviceConnection::onErrorOccurred" << socketError;
|
||||
if (m_otaProgress == 99) { // 99 表示设备正在OTA重启,需要重连
|
||||
if (socket->state() == QTcpSocket::UnconnectedState) {
|
||||
LOG(info) << "try reconnect after ota.";
|
||||
socket->connectToHost(m_infomation.ip, 8000);
|
||||
}
|
||||
}
|
||||
LOG(info) << "DeviceConnection::onErrorOccurred" << socketError;
|
||||
}
|
||||
|
||||
void DeviceConnection::timerEvent(QTimerEvent *event) {
|
||||
|
@ -18,6 +18,7 @@ class DeviceConnection : public QObject {
|
||||
QML_UNCREATABLE("Only created in C++...")
|
||||
|
||||
public:
|
||||
constexpr static auto WirelessAddress = "192.168.10.2";
|
||||
enum Resolution {
|
||||
Video_360P = 0,
|
||||
Video_720P,
|
||||
@ -115,6 +116,7 @@ private:
|
||||
QTcpSocket *m_commandSocket = nullptr;
|
||||
|
||||
QTcpSocket *m_h264Socket = nullptr;
|
||||
bool m_videoEnabled = false;
|
||||
bool m_receivedFirstJsonReply = false;
|
||||
|
||||
QByteArray m_commandBuffer;
|
||||
|
@ -7,6 +7,38 @@
|
||||
#include <QUdpSocket>
|
||||
#include <boost/json/parse.hpp>
|
||||
|
||||
static QHostAddress calculateNetworkAddress(const QHostAddress &ip, const QHostAddress &netmask) {
|
||||
quint32 ipInt = ip.toIPv4Address();
|
||||
quint32 netmaskInt = netmask.toIPv4Address();
|
||||
quint32 networkInt = ipInt & netmaskInt;
|
||||
return QHostAddress(networkInt);
|
||||
}
|
||||
|
||||
static bool isSameNetwork(const QHostAddress &ip1, const QHostAddress &netmask1, const QHostAddress &ip2) {
|
||||
QHostAddress network1 = calculateNetworkAddress(ip1, netmask1);
|
||||
QHostAddress network2 = calculateNetworkAddress(ip2, netmask1); // Using the same netmask for the target IP
|
||||
return network1 == network2;
|
||||
}
|
||||
|
||||
static bool isTargetIPInSameNetwork(const QHostAddress &targetIP) {
|
||||
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &iface : interfaces) {
|
||||
QList<QNetworkAddressEntry> entries = iface.addressEntries();
|
||||
for (const QNetworkAddressEntry &entry : entries) {
|
||||
QHostAddress ip = entry.ip();
|
||||
QHostAddress netmask = entry.netmask();
|
||||
|
||||
if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
bool sameNetwork = isSameNetwork(ip, netmask, targetIP);
|
||||
if (sameNetwork) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceListModel::DeviceListModel(QObject *parent) : QAbstractListModel{parent} {
|
||||
m_broadcastSocket = new QUdpSocket(this);
|
||||
}
|
||||
@ -72,6 +104,12 @@ void DeviceListModel::startSearchDevice() {
|
||||
LOG(error) << "app is searching device.";
|
||||
return;
|
||||
}
|
||||
if (!m_udpSockets.empty()) {
|
||||
for (auto &socket : m_udpSockets) {
|
||||
socket->deleteLater();
|
||||
}
|
||||
m_udpSockets.clear();
|
||||
}
|
||||
beginResetModel();
|
||||
m_devices.clear();
|
||||
endResetModel();
|
||||
@ -143,6 +181,7 @@ void DeviceListModel::onDeviceReplyReadyRead() {
|
||||
auto udp = dynamic_cast<QUdpSocket *>(sender());
|
||||
while (udp->hasPendingDatagrams()) {
|
||||
QNetworkDatagram datagram = udp->receiveDatagram();
|
||||
if (isTargetIPInSameNetwork(datagram.senderAddress())) { // 设备开机时可能会广播一个 192.168.2.10 的地址
|
||||
auto replyVale = boost::json::parse(datagram.data().toStdString());
|
||||
auto &reply = replyVale.as_object();
|
||||
DeviceConnection::Infomation device;
|
||||
@ -163,17 +202,35 @@ void DeviceListModel::onDeviceReplyReadyRead() {
|
||||
return item->infomation().deviceId == device.deviceId;
|
||||
});
|
||||
if (iterator == m_devices.cend()) {
|
||||
auto connection = std::shared_ptr<DeviceConnection>(new DeviceConnection(),
|
||||
[](DeviceConnection *self) { self->deleteLater(); });
|
||||
if (m_timerId >= 0) { // 只有在搜索设备的过程中,才加入新设备
|
||||
auto connection = std::shared_ptr<DeviceConnection>(
|
||||
new DeviceConnection(), [](DeviceConnection *self) { self->deleteLater(); });
|
||||
connect(connection.get(), &DeviceConnection::connected, this, &DeviceListModel::onDeviceConnected);
|
||||
connect(connection.get(), &DeviceConnection::disconnected, this, &DeviceListModel::onDeviceDisconnected);
|
||||
connect(connection.get(), &DeviceConnection::disconnected, this,
|
||||
&DeviceListModel::onDeviceDisconnected);
|
||||
connection->connect(device);
|
||||
beginInsertRows(QModelIndex(), m_devices.size(), m_devices.size());
|
||||
m_devices.push_back(connection);
|
||||
endInsertRows();
|
||||
}
|
||||
LOG(info) << "Received datagram from " << datagram.senderAddress().toString().toStdString() << ":"
|
||||
<< datagram.senderPort() << ", Data: " << datagram.data().toStdString();
|
||||
} else {
|
||||
auto info = (*iterator)->infomation();
|
||||
if ((m_timerId < 0) ||
|
||||
((info.ip == DeviceConnection::WirelessAddress) && (device.ip != DeviceConnection::WirelessAddress)) ||
|
||||
((device.ip != DeviceConnection::WirelessAddress) && (device.ip != info.ip))) {
|
||||
QList<int> roles;
|
||||
roles << OnlineStatusRole << IpRole;
|
||||
int row = std::distance(m_devices.cbegin(), iterator);
|
||||
emit dataChanged(index(row), index(row), roles);
|
||||
(*iterator)->connect(device);
|
||||
LOG(info) << "device: " << device.deviceId.toStdString() << " back online";
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(info) << datagram.destinationAddress().toString().toStdString() << ":" << datagram.destinationPort()
|
||||
<< " received datagram from " << datagram.senderAddress().toString().toStdString() << ":"
|
||||
<< datagram.senderPort() << ", Data: " << datagram.data().toStdString()
|
||||
<< ", same network: " << isTargetIPInSameNetwork(datagram.senderAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,12 +258,6 @@ void DeviceListModel::stopSearchDevice() {
|
||||
killTimer(m_timerId);
|
||||
m_timerId = -1;
|
||||
}
|
||||
if (!m_udpSockets.empty()) {
|
||||
for (auto &socket : m_udpSockets) {
|
||||
socket->deleteLater();
|
||||
}
|
||||
m_udpSockets.clear();
|
||||
}
|
||||
emit isSearchingChanged();
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ Popup {
|
||||
placeholderText: "请选择升级bin文件"
|
||||
}
|
||||
Button {
|
||||
enabled: otaFinished
|
||||
text: "选择"
|
||||
onClicked: fileDialog.open()
|
||||
}
|
||||
@ -76,6 +77,7 @@ Popup {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Button {
|
||||
enabled: otaFinished
|
||||
text: "开始"
|
||||
Layout.alignment: Qt.AlignRight
|
||||
onClicked: {
|
||||
@ -119,7 +121,10 @@ Popup {
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if(!visible){
|
||||
progressBar.value = 0
|
||||
otaMessage.color = "black"
|
||||
progressText.text = "0%"
|
||||
otaMessage.text = "请选择升级文件,点击开始按钮升级模组"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user