diff --git a/Application.cpp b/Application.cpp index 1001deb..493d36d 100644 --- a/Application.cpp +++ b/Application.cpp @@ -164,6 +164,35 @@ void Application::updateShieldedAreaPoints(const QList &points) { } } +bool Application::currentDeviceFlip() const { + return m_currentDeviceFlip; +} +void Application::setCurrentDeviceFlip(bool flip) { + if (m_currentDeviceFlip != flip) { + m_currentDeviceFlip = flip; + emit currentDeviceFlipChanged(); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateFlip(flip); + } + } +} + +int Application::currentDeviceRotation() const { + return m_currentDeviceRotation; +} + +void Application::setCurrentDeviceRotation(int rotation) { + if (m_currentDeviceRotation != rotation) { + m_currentDeviceRotation = rotation; + emit currentDeviceRotationChanged(); + if (!m_device.expired()) { + auto device = m_device.lock(); + device->updateRotation(rotation); + } + } +} + void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway, const QString &dns) { if (!m_device.expired()) { @@ -180,6 +209,8 @@ void Application::updateNetworkInfomation(bool dhcp, const QString &ip, const QS void Application::connectToDevice(int index) { if (!m_device.expired()) { auto device = m_device.lock(); + disconnect(device.get(), &DeviceConnection::rotationChanged, this, &Application::onDeviceRotationChanged); + disconnect(device.get(), &DeviceConnection::flipChanged, this, &Application::onDeviceFlipChanged); disconnect(device.get(), &DeviceConnection::openDoorAreaChanged, this, &Application::onDeviceOpenDoorArea); disconnect(device.get(), &DeviceConnection::shieldedAreaChanged, this, &Application::onDeviceShieldedArea); disconnect(device.get(), &DeviceConnection::antiClipAreaChanged, this, &Application::onDeviceAntiClipArea); @@ -202,6 +233,8 @@ void Application::connectToDevice(int index) { auto device = m_devices->device(index); m_device = device; + connect(device.get(), &DeviceConnection::rotationChanged, this, &Application::onDeviceRotationChanged); + connect(device.get(), &DeviceConnection::flipChanged, this, &Application::onDeviceFlipChanged); connect(device.get(), &DeviceConnection::openDoorAreaChanged, this, &Application::onDeviceOpenDoorArea); connect(device.get(), &DeviceConnection::shieldedAreaChanged, this, &Application::onDeviceShieldedArea); connect(device.get(), &DeviceConnection::antiClipAreaChanged, this, &Application::onDeviceAntiClipArea); @@ -220,16 +253,20 @@ void Application::connectToDevice(int index) { } }); 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; + auto info = device->infomation(); + m_currentOpenDoorAreaWay = info.openDoorAreaWay; + m_currentOpenDoorAreaPoints = info.openDoorArea; + m_currentShieldedAreaEnabled = info.shieldedAreaEnabled; + m_currentShieldedAreaPoints = info.shieldedArea; + m_currentAntiClipAreaEnabled = info.antiClipAreaEnabled; + m_currentAntiClipAreaPoints = info.antiClipArea; m_currentNetworkInfomation = device->networkInfomation(); m_currentFirmware = device->infomation().firmwareVersion; m_currentDeviceConnected = device->isConnected(); + m_currentDeviceFlip = info.flip; + m_currentDeviceRotation = info.rotation; + emit currentDeviceRotationChanged(); + emit currentDeviceFlipChanged(); emit currentOpenDoorAreaPointsChanged(); emit currentShieldedAreaPointsChanged(); emit currentAntiClipAreaPointsChanged(); @@ -274,6 +311,13 @@ void Application::onDeviceOpenDoorArea(DeviceConnection::AreaWay way, const QLis setCurrentOpenDoorAreaPoints(points); } +void Application::onDeviceRotationChanged(int rotation) { + setCurrentDeviceRotation(rotation); +} +void Application::onDeviceFlipChanged(bool flip) { + setCurrentDeviceFlip(flip); +} + void Application::onDeviceShieldedArea(bool enabled, const QList &points) { setCurrentShieldedAreaEnabled(enabled); setCurrentShieldedAreaPoints(points); diff --git a/Application.h b/Application.h index 814b273..0a5061c 100644 --- a/Application.h +++ b/Application.h @@ -40,6 +40,10 @@ class Application : public QObject { NetworkInfomation currentNetworkInfomation READ currentNetworkInfomation NOTIFY currentNetworkInfomationChanged) Q_PROPERTY(QString currentFirmware MEMBER m_currentFirmware NOTIFY currentFirmwareChanged) Q_PROPERTY(bool currentDeviceConnected MEMBER m_currentDeviceConnected NOTIFY currentDeviceConnectedChanged) + + Q_PROPERTY(bool currentDeviceFlip READ currentDeviceFlip WRITE setCurrentDeviceFlip NOTIFY currentDeviceFlipChanged) + Q_PROPERTY(int currentDeviceRotation READ currentDeviceRotation WRITE setCurrentDeviceRotation NOTIFY + currentDeviceRotationChanged) friend class Amass::Singleton; public: @@ -64,6 +68,12 @@ public: QList currentAntiClipAreaPoints() const; void setCurrentAntiClipAreaPoints(const QList &points); + bool currentDeviceFlip() const; + void setCurrentDeviceFlip(bool flip); + + int currentDeviceRotation() const; + void setCurrentDeviceRotation(int rotation); + Q_INVOKABLE void updateOpenDoorAreaPoints(const QList &points); Q_INVOKABLE void updateAntiClipAreaPoints(const QList &points); Q_INVOKABLE void updateShieldedAreaPoints(const QList &points); @@ -88,10 +98,14 @@ signals: void currentFirmwareChanged(); void currentDeviceConnectedChanged(); void currentDeviceOtaProgressChanged(bool status, int progress, const QString &message); + void currentDeviceFlipChanged(); + void currentDeviceRotationChanged(); void newMessage(int type, const QString &title, const QString &message); protected: Application(int &argc, char **argv); + void onDeviceRotationChanged(int rotation); + void onDeviceFlipChanged(bool flip); void onDeviceOpenDoorArea(DeviceConnection::AreaWay way, const QList &points); void onDeviceShieldedArea(bool enabled, const QList &points); void onDeviceAntiClipArea(bool enabled, const QList &points); @@ -118,6 +132,8 @@ private: NetworkInfomation m_currentNetworkInfomation; QString m_currentFirmware; bool m_currentDeviceConnected = false; + bool m_currentDeviceFlip = false; + int m_currentDeviceRotation = 0; }; #endif // APPLICATION_H diff --git a/DeviceConnection.cpp b/DeviceConnection.cpp index 062fa1a..4030996 100644 --- a/DeviceConnection.cpp +++ b/DeviceConnection.cpp @@ -73,10 +73,6 @@ void DeviceConnection::connect(const Infomation &infomation) { m_h264Socket->connectToHost(infomation.ip, 8000); } -DeviceConnection::Area DeviceConnection::area() const { - return m_area; -} - NetworkInfomation DeviceConnection::networkInfomation() const { return m_networkInfomation; } @@ -262,6 +258,44 @@ void DeviceConnection::requestResolution(Resolution resolution) { m_requests.push(task); } +void DeviceConnection::updateRotation(int rotation) { + Task task; + task.command = "a23imagerotate_setdata"; + task.task = [this, rotation]() { + boost::json::object request; + request["func"] = "a23imagerotate_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = std::to_string(rotation); + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "updateRotation: " << text; + }; + if (m_requests.empty()) { + task.task(); + } + m_requests.push(task); +} +void DeviceConnection::updateFlip(bool flip) { + Task task; + task.command = "a04imageflipping_setdata"; + task.task = [this, flip]() { + boost::json::object request; + request["func"] = "a04imageflipping_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = flip ? "2" : "1"; + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + }; + if (m_requests.empty()) { + task.task(); + } + m_requests.push(task); +} + void DeviceConnection::requestVersion() { Task task; task.command = "a15devicedetail_getdata"; @@ -281,6 +315,27 @@ void DeviceConnection::requestVersion() { m_requests.push(task); } +void DeviceConnection::requestVideoInformation() { + constexpr const char *commands[] = {"a23imagerotate_getdata", "a04imageflipping_getdata"}; + for (auto command : commands) { + Task task; + task.command = command; + task.task = [this, command]() { + boost::json::object request; + request["func"] = command; + request["deviceid"] = "0"; + boost::json::object data; + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + }; + if (m_requests.empty()) { + task.task(); + } + m_requests.push(task); + } +} + void DeviceConnection::requestNetworkInfomation() { Task task; task.command = "netconfig_getdata"; @@ -457,8 +512,8 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const } else if (value == "2") { way = Quadrangle; } - m_area.openDoorAreaWay = way; - m_area.openDoorArea = points; + m_infomation.openDoorAreaWay = way; + m_infomation.openDoorArea = points; emit openDoorAreaChanged(way, points); } else if (function == "a03opendoor4_getdata") { auto &data = reply.at("data").as_object(); @@ -472,8 +527,8 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const point.setY(obj.at("y").as_double()); points.push_back(point); } - m_area.shieldedAreaEnabled = value == "1"; - m_area.shieldedArea = points; + m_infomation.shieldedAreaEnabled = value == "1"; + m_infomation.shieldedArea = points; emit shieldedAreaChanged(value == "1", points); } else if (function == "a03opendoor5_getdata") { auto &data = reply.at("data").as_object(); @@ -487,8 +542,8 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const point.setY(obj.at("y").as_double()); points.push_back(point); } - m_area.antiClipAreaEnabled = value == "1"; - m_area.antiClipArea = points; + m_infomation.antiClipAreaEnabled = value == "1"; + m_infomation.antiClipArea = points; emit antiClipAreaChanged(value == "1", points); } else if (function == "netconfig_getdata") { auto &data = reply.at("data").as_object(); @@ -579,6 +634,40 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const } emit otaProgressChanged(false, m_otaProgress, tip); } + } else if (function == "a23imagerotate_getdata") { + // {"data":{"value":"2"},"deviceid":"0","flag":"ok","func":"a23imagerotate_getdata"} + auto &data = reply.at("data").as_object(); + auto &value = data.at("value").as_string(); + m_infomation.rotation = std::stoi(static_cast(value)); + emit rotationChanged(m_infomation.rotation); + } else if (function == "a04imageflipping_getdata") { + // {"data":{"value":"1"},"deviceid":"0","flag":"ok","func":"a04imageflipping_getdata"} + auto &data = reply.at("data").as_object(); + auto &value = data.at("value").as_string(); + m_infomation.flip = value == "2"; + emit flipChanged(m_infomation.flip); + } else if (function == "a04imageflipping_setdata") { + if ((task != nullptr) && (task->command.toStdString() == function)) { + if (task->timeoutTimer) { + task->timeoutTimer->stop(); + } + bool status = true; + if (task->future) { + task->future->reportFinished(&status); + } + } + requestVideoInformation(); + } else if (function == "a23imagerotate_setdata") { + if ((task != nullptr) && (task->command.toStdString() == function)) { + if (task->timeoutTimer) { + task->timeoutTimer->stop(); + } + bool status = true; + if (task->future) { + task->future->reportFinished(&status); + } + } + requestVideoInformation(); } else { LOG(warning) << "unknown reply: " << replyText; } @@ -593,6 +682,7 @@ void DeviceConnection::onConnected() { requestShieldedArea(); requestAntiClipArea(); requestNetworkInfomation(); + requestVideoInformation(); emit connected(); m_timerId = startTimer(2500); if (m_otaProgress == 99) { diff --git a/DeviceConnection.h b/DeviceConnection.h index aebab30..592d05f 100644 --- a/DeviceConnection.h +++ b/DeviceConnection.h @@ -34,11 +34,10 @@ public: QString softwareVersion; QString firmwareVersion; QString ip; - }; - Q_ENUM(AreaWay) - class Area { - public: + int rotation = 0; + bool flip = false; + QList openDoorArea; AreaWay openDoorAreaWay; @@ -48,6 +47,7 @@ public: QList antiClipArea; bool antiClipAreaEnabled; }; + Q_ENUM(AreaWay) using H264FrameCallback = std::function; DeviceConnection(QObject *parent = nullptr); @@ -60,7 +60,6 @@ public: void setLiveStreamEnabled(bool enabled); NetworkInfomation networkInfomation() const; - Area area() const; void requestOpenDoorArea(); QFuture updateOpenDoorAreaPoints(AreaWay way, const QList &points); @@ -73,6 +72,9 @@ public: QFuture updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway, const QString &dns); void requestVersion(); + void requestVideoInformation(); + void updateRotation(int rotation); + void updateFlip(bool flip); /** * @brief 对设备升级OTA,主要有几个步骤 @@ -91,6 +93,8 @@ signals: void openDoorAreaChanged(AreaWay way, const QList &points); void shieldedAreaChanged(bool enabled, const QList &points); void antiClipAreaChanged(bool enabled, const QList &points); + void rotationChanged(int rotation); + void flipChanged(bool flip); void networkInfomationChanged(const NetworkInfomation &info); void firmwareChanged(const QString &firmware); void otaProgressChanged(bool status, int progress, const QString &message); @@ -133,7 +137,6 @@ private: std::queue m_requests; int m_timerId = -1; int heartbeats = 0; - Area m_area; NetworkInfomation m_networkInfomation; QString m_firmware; }; diff --git a/qml/DeviceView.qml b/qml/DeviceView.qml index e4c9ed7..f5670e3 100644 --- a/qml/DeviceView.qml +++ b/qml/DeviceView.qml @@ -16,6 +16,9 @@ Item { property color antiClipAreaColor: "blue" property var antiClipAreaPoints: [] property bool antiClipAreaEnabled: false + property alias flip: flipSwitch.checked + property alias videoRotation: rotateComboBox.currentIndex + Item { anchors.left: parent.left anchors.right: parent.right @@ -246,6 +249,35 @@ Item { columns: 2 spacing: 10 verticalItemAlignment: Qt.AlignVCenter + + Label { text: qsTr("图像: ") } + + Row { + enabled: root.enabled + Label { + anchors.verticalCenter: parent.verticalCenter + text: qsTr("旋转") + } + Item {width: 10; height:10} + ComboBox { + id: rotateComboBox + model: ["0°","90°","180°","270°"] + onCurrentIndexChanged: { + App.currentDeviceRotation = rotateComboBox.currentIndex + } + } + Item {width: 70; height:10} + Label { + anchors.verticalCenter: parent.verticalCenter + text: qsTr("翻转") + } + Item {width: 10; height:10} + Switch { + id: flipSwitch + onToggled: App.currentDeviceFlip=flipSwitch.checked + } + } + Label { text: qsTr("开门区域: ") } diff --git a/qml/Main.qml b/qml/Main.qml index 5789317..fc63aee 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -119,6 +119,8 @@ ApplicationWindow { shieldedAreaPoints: App.currentShieldedAreaPoints antiClipAreaEnabled: App.currentAntiClipAreaEnabled antiClipAreaPoints: App.currentAntiClipAreaPoints + flip: App.currentDeviceFlip + videoRotation: App.currentDeviceRotation } NetworkSettingPopup {