From 5adb0d783d19891c3109cfead124fca85204e798 Mon Sep 17 00:00:00 2001 From: luocai Date: Tue, 20 Aug 2024 09:29:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=9E=E6=8E=A5=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application.cpp | 90 +++++++++++++++++++++++++++++++-------------- Application.h | 4 +- DeviceListModel.cpp | 85 ++++++++++++++++++++++++++++++++++-------- DeviceListModel.h | 15 +++----- DeviceView.qml | 4 +- Main.qml | 14 ++++++- 6 files changed, 157 insertions(+), 55 deletions(-) diff --git a/Application.cpp b/Application.cpp index 7226bbf..aaec9cd 100644 --- a/Application.cpp +++ b/Application.cpp @@ -38,8 +38,9 @@ void Application::setCurrentOpenDoorAreaWay(DeviceConnection::AreaWay way) { } emit currentOpenDoorAreaWayChanged(); - if (m_device != nullptr) { - m_device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaWay, m_currentOpenDoorAreaPoints); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaWay, m_currentOpenDoorAreaPoints); } } @@ -72,9 +73,9 @@ void Application::setCurrentShieldedAreaEnabled(bool enabled) { m_currentShieldedAreaPoints << QPointF(6, 6) << QPointF(40, 60) << QPointF(590, 6) << QPointF(630, 60); emit currentShieldedAreaPointsChanged(); } - - if (m_device != nullptr) { - m_device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, m_currentShieldedAreaPoints); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, m_currentShieldedAreaPoints); } } } @@ -98,8 +99,9 @@ void Application::setCurrentAntiClipAreaEnabled(bool enabled) { if (m_currentAntiClipAreaEnabled != enabled) { m_currentAntiClipAreaEnabled = enabled; emit currentAntiClipAreaEnabledChanged(); - if (m_device != nullptr) { - m_device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, m_currentAntiClipAreaPoints); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, m_currentAntiClipAreaPoints); } } } @@ -116,52 +118,86 @@ void Application::setCurrentAntiClipAreaPoints(const QList &points) { } void Application::updateOpenDoorAreaPoints(const QList &points) { - if (m_device != nullptr) { - m_device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaWay, points); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaWay, points); } } void Application::updateAntiClipAreaPoints(const QList &points) { - m_device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, points); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, points); + } } void Application::updateShieldedAreaPoints(const QList &points) { - m_device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, points); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, points); + } } void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway) { - LOG(info) << dhcp; - LOG(info) << ip.toStdString(); - if (m_device != nullptr) { - m_device->updateNetworkInfomation(dhcp, ip, netmask, gateway); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateNetworkInfomation(dhcp, ip, netmask, gateway); } } -void Application::connectToDevice(const QString &address) { - if (m_device != nullptr) { - m_device->deleteLater(); +void Application::connectToDevice(int index) { + if (!m_device.expired()) { + auto device = m_device.lock(); + disconnect(device.get(), &DeviceConnection::currentOpenDoorAreaChanged, this, + &Application::onDeviceOpenDoorArea); + disconnect(device.get(), &DeviceConnection::currentShieldedAreaChanged, this, + &Application::onDeviceShieldedArea); + disconnect(device.get(), &DeviceConnection::currentAntiClipAreaChanged, this, + &Application::onDeviceAntiClipArea); + disconnect(device.get(), &DeviceConnection::currentNetworkInfomationChanged, this, + &Application::onDeviceNetworkInfomation); + device->setH264FrameCallback(DeviceConnection::H264FrameCallback()); + device->setLiveStreamEnabled(false); } + auto device = m_devices->device(index); + m_device = device; - m_device = new DeviceConnection(); - connect(m_device, &DeviceConnection::currentOpenDoorAreaChanged, this, &Application::onDeviceOpenDoorArea); - connect(m_device, &DeviceConnection::currentShieldedAreaChanged, this, &Application::onDeviceShieldedArea); - connect(m_device, &DeviceConnection::currentAntiClipAreaChanged, this, &Application::onDeviceAntiClipArea); - connect(m_device, &DeviceConnection::currentNetworkInfomationChanged, this, + connect(device.get(), &DeviceConnection::currentOpenDoorAreaChanged, this, &Application::onDeviceOpenDoorArea); + connect(device.get(), &DeviceConnection::currentShieldedAreaChanged, this, &Application::onDeviceShieldedArea); + connect(device.get(), &DeviceConnection::currentAntiClipAreaChanged, this, &Application::onDeviceAntiClipArea); + connect(device.get(), &DeviceConnection::currentNetworkInfomationChanged, this, &Application::onDeviceNetworkInfomation); - m_device->connect(address); - m_device->setH264FrameCallback([this](const char *data, uint32_t size) { + device->setH264FrameCallback([this](const char *data, uint32_t size) { auto image = m_player->decode((const uint8_t *)data, size); if (image) { m_videoFrameProvider->setImage(*image); emit newVideoFrame(); } }); + device->setLiveStreamEnabled(true); + auto area = device->area(); + + m_currentOpenDoorAreaWay = area.openDoorAreaWay; + m_currentOpenDoorAreaPoints = area.openDoorArea; + m_currentShieldedAreaEnabled = area.shieldedAreaEnabled; + m_currentShieldedAreaPoints = area.shieldedArea; + m_currentAntiClipAreaEnabled = area.antiClipAreaEnabled; + m_currentAntiClipAreaPoints = area.antiClipArea; + m_currentNetworkInfomation = device->networkInfomation(); + emit currentOpenDoorAreaPointsChanged(); + emit currentShieldedAreaPointsChanged(); + emit currentAntiClipAreaPointsChanged(); + emit currentOpenDoorAreaWayChanged(); + emit currentShieldedAreaEnabledChanged(); + emit currentAntiClipAreaEnabledChanged(); + emit currentNetworkInfomationChanged(); } void Application::upgradeDevice(const QString &file) { - if (m_device != nullptr) { - m_device->requestOta(file); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->requestOta(file); } } diff --git a/Application.h b/Application.h index e642a93..bbe730d 100644 --- a/Application.h +++ b/Application.h @@ -63,7 +63,7 @@ public: Q_INVOKABLE void updateShieldedAreaPoints(const QList &points); Q_INVOKABLE void updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway); - Q_INVOKABLE void connectToDevice(const QString &address); + Q_INVOKABLE void connectToDevice(int index); Q_INVOKABLE void upgradeDevice(const QString &file); int exec(); @@ -90,7 +90,7 @@ private: std::shared_ptr m_app; VideoFrameProvider *m_videoFrameProvider = nullptr; std::shared_ptr m_player; - DeviceConnection *m_device = nullptr; + std::weak_ptr m_device; DeviceListModel *m_devices = nullptr; DeviceConnection::AreaWay m_currentOpenDoorAreaWay = DeviceConnection::Diabled; diff --git a/DeviceListModel.cpp b/DeviceListModel.cpp index d6392db..cb90733 100644 --- a/DeviceListModel.cpp +++ b/DeviceListModel.cpp @@ -1,5 +1,6 @@ #include "DeviceListModel.h" #include "BoostLog.h" +#include "DeviceConnection.h" #include #include #include @@ -17,14 +18,20 @@ int DeviceListModel::rowCount(const QModelIndex &parent) const { QVariant DeviceListModel::data(const QModelIndex &index, int role) const { QVariant ret; auto row = index.row(); + if (row >= m_devices.size()) { + return ret; + } + auto info = m_devices.at(row)->infomation(); if (role == DeviceIdRole) { - ret = m_devices.at(row).deviceId; + ret = info.deviceId; } else if (role == FirmwareVersionRole) { - ret = m_devices.at(row).firmwareVersion; + ret = info.firmwareVersion; } else if (role == SoftwareVersionRole) { - ret = m_devices.at(row).softwareVersion; + ret = info.softwareVersion; } else if (role == IpRole) { - ret = m_devices.at(row).ip; + ret = info.ip; + } else if (role == OnlineStatusRole) { + ret = m_devices.at(row)->isConnected(); } return ret; } @@ -35,26 +42,40 @@ QHash DeviceListModel::roleNames() const { roleNames.insert(FirmwareVersionRole, "firmwareVersion"); roleNames.insert(SoftwareVersionRole, "softwareVersion"); roleNames.insert(IpRole, "ip"); + roleNames.insert(OnlineStatusRole, "onlineStatus"); return roleNames; } QVariantMap DeviceListModel::get(int index) const { QVariantMap map; if (index >= 0 && index < m_devices.size()) { - map["firmwareVersion"] = m_devices[index].firmwareVersion; - map["softwareVersion"] = m_devices[index].softwareVersion; - map["deviceId"] = m_devices[index].deviceId; - map["ip"] = m_devices[index].ip; + auto info = m_devices.at(index)->infomation(); + map["firmwareVersion"] = info.firmwareVersion; + map["softwareVersion"] = info.softwareVersion; + map["deviceId"] = info.deviceId; + map["ip"] = info.ip; + map["onlineStatus"] = m_devices.at(index)->isConnected(); } return map; } +std::shared_ptr DeviceListModel::device(int index) { + std::shared_ptr ret; + if (index < m_devices.size()) { + ret = m_devices.at(index); + } + return ret; +} + void DeviceListModel::startSearchDevice() { if (m_timerId >= 0) { LOG(error) << "app is searching device."; return; } beginResetModel(); + for (auto &device : m_devices) { + device->deleteLater(); + } m_devices.clear(); endResetModel(); auto interfaces = QNetworkInterface::allInterfaces(); @@ -93,24 +114,58 @@ float DeviceListModel::searchProgress() const { return static_cast(m_retries) * 100 / RetryCount; } +void DeviceListModel::onDeviceConnected() { + auto device = dynamic_cast(sender()); + auto iterator = + std::find_if(m_devices.cbegin(), m_devices.cend(), + [device](const std::shared_ptr &item) { return item.get() == device; }); + if (iterator != m_devices.cend()) { + QList roles; + roles << OnlineStatusRole; + int row = std::distance(m_devices.cbegin(), iterator); + emit dataChanged(index(row), index(row), roles); + LOG(info) << "device " << row << " connected."; + } +} + +void DeviceListModel::onDeviceDisconnected() { + auto device = dynamic_cast(sender()); + auto iterator = + std::find_if(m_devices.cbegin(), m_devices.cend(), + [device](const std::shared_ptr &item) { return item.get() == device; }); + if (iterator != m_devices.cend()) { + int row = std::distance(m_devices.cbegin(), iterator); + QList roles; + roles << OnlineStatusRole; + emit dataChanged(index(row), index(row), roles); + LOG(info) << "device " << row << " disconnected."; + } +} + void DeviceListModel::onDeviceReplyReadyRead() { auto udp = dynamic_cast(sender()); while (udp->hasPendingDatagrams()) { QNetworkDatagram datagram = udp->receiveDatagram(); auto replyVale = boost::json::parse(datagram.data().toStdString()); auto &reply = replyVale.as_object(); - DeviceInfomation device; + DeviceConnection::Infomation device; device.deviceId = QString::fromStdString(std::string(reply.at("devid").as_string())); device.firmwareVersion = QString::fromStdString(std::string(reply.at("fw_ver").as_string())); device.softwareVersion = QString::fromStdString(std::string(reply.at("sw_ver").as_string())); device.ip = datagram.senderAddress().toString(); - auto iterator = std::find_if(m_devices.cbegin(), m_devices.cend(), [&device](const DeviceInfomation &item) { - return item.deviceId == device.deviceId; - }); + auto iterator = std::find_if(m_devices.cbegin(), m_devices.cend(), + [&device](const std::shared_ptr &item) { + return item->infomation().deviceId == device.deviceId; + }); if (iterator == m_devices.cend()) { + auto connection = std::shared_ptr(new DeviceConnection(), + [](DeviceConnection *self) { self->deleteLater(); }); + connect(connection.get(), &DeviceConnection::connected, this, &DeviceListModel::onDeviceConnected); + connect(connection.get(), &DeviceConnection::disconnected, this, &DeviceListModel::onDeviceDisconnected); + connection->connect(device); beginInsertRows(QModelIndex(), m_devices.size(), m_devices.size()); - m_devices.push_back(device); + m_devices.push_back(connection); endInsertRows(); } LOG(info) << "Received datagram from " << datagram.senderAddress().toString().toStdString() << ":" @@ -129,8 +184,8 @@ void DeviceListModel::broadcast() { for (const QNetworkAddressEntry &entry : entries) { if (entry.broadcast().toIPv4Address()) { m_broadcastSocket->writeDatagram(datagram, entry.broadcast(), BroadcastPort); - LOG(info) << "Broadcasted datagram: " << datagram.toStdString() << " to " - << entry.broadcast().toString().toStdString() << ":" << BroadcastPort; + // LOG(info) << "Broadcasted datagram: " << datagram.toStdString() << " to " + // << entry.broadcast().toString().toStdString() << ":" << BroadcastPort; } } } diff --git a/DeviceListModel.h b/DeviceListModel.h index fcb9e94..4da6c66 100644 --- a/DeviceListModel.h +++ b/DeviceListModel.h @@ -5,14 +5,7 @@ #include class QUdpSocket; - -class DeviceInfomation { -public: - QString deviceId; - QString softwareVersion; - QString firmwareVersion; - QString ip; -}; +class DeviceConnection; class DeviceListModel : public QAbstractListModel { Q_OBJECT @@ -30,12 +23,14 @@ public: FirmwareVersionRole, SoftwareVersionRole, IpRole, + OnlineStatusRole, }; DeviceListModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const final; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const final; QHash roleNames() const final; Q_INVOKABLE QVariantMap get(int index) const; + std::shared_ptr device(int index); Q_INVOKABLE void startSearchDevice(); bool isSearching() const; float searchProgress() const; @@ -45,13 +40,15 @@ signals: void searchProgressChanged(); protected: + void onDeviceConnected(); + void onDeviceDisconnected(); void onDeviceReplyReadyRead(); void broadcast(); void stopSearchDevice(); void timerEvent(QTimerEvent *event); private: - std::vector m_devices; + std::vector> m_devices; std::list m_udpSockets; QUdpSocket *m_broadcastSocket = nullptr; int m_timerId = -1; diff --git a/DeviceView.qml b/DeviceView.qml index 0e5e6fe..f6c55f4 100644 --- a/DeviceView.qml +++ b/DeviceView.qml @@ -9,7 +9,7 @@ Item { property color openDoorAreaColor: "green" property var openDoorAreaPoints: [] property int openDoorAreaWay: 0 - property color shieldedAreaColor: "yellow" + property color shieldedAreaColor: "yellow" property var shieldedAreaPoints: [] property bool shieldedAreaEnabled: false property color antiClipAreaColor: "blue" @@ -332,9 +332,11 @@ Item { repeater.model = openDoorAreaPoints } function onCurrentShieldedAreaPointsChanged() { + shieldedAreaRepeater.model = shieldedAreaPoints canvas.requestPaint() } function onCurrentAntiClipAreaPointsChanged() { + antiAreaRepeater.model = antiClipAreaPoints canvas.requestPaint() } function onCurrentOpenDoorAreaWayChanged(){ diff --git a/Main.qml b/Main.qml index c102ee9..b24d700 100644 --- a/Main.qml +++ b/Main.qml @@ -19,6 +19,9 @@ ApplicationWindow { App.devices.startSearchDevice() } } + Text { + text: `设备总数: ${deviceList.count}` + } Row { Layout.alignment: Qt.AlignRight Text { @@ -49,12 +52,21 @@ ApplicationWindow { anchors.fill: parent spacing: 10 Text { + anchors.verticalCenter: parent.verticalCenter text: deviceId } Item {} Text { + anchors.verticalCenter: parent.verticalCenter text: ip } + Rectangle { + anchors.verticalCenter: parent.verticalCenter + color: onlineStatus ? "green":"black" + width: 10 + height: 10 + radius: 5 + } } MouseArea { anchors.fill: parent @@ -69,7 +81,7 @@ ApplicationWindow { } onCurrentIndexChanged: { deviceVersion.text = App.devices.get(deviceList.currentIndex).softwareVersion; - App.connectToDevice(App.devices.get(deviceList.currentIndex).ip) + App.connectToDevice(deviceList.currentIndex) } ProgressBar { anchors.left: parent.left