See "heimdall"; Android Qt/C++ client for the private doorbell project heimdall. Uses MQTT to communicate.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
heimdall-client/main.qml

286 lines
4.2 KiB

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import QtMultimedia 5.12
import MqttClient 1.0
import DoorOpener 1.0
Window {
width: 360
height: 640
visible: true
title: qsTr("heimdall")
// background image
Image {
source: "qrc:/res/bg.jpg"
anchors.fill: parent
fillMode: Image.Pad
opacity: .25
}
// mqtt client
MqttClient {
id: client
Component.onCompleted: {
// TODO this is bad architecture. it should be safe to know when the connection is established. (see DoorOpener.cpp)
connectToHost()
}
onConnected: {
subscribe()
}
onDisconnected: {
video.stop()
}
onStateChanged: {
stateIndicator.color = getState()
stateIndicatorText.text = color == "green" ? "✔" : "x"
}
onMessageReceived: {
notificationClient.notification = Qt.formatDateTime(new Date(), "hh:mm:ss") + " Uhr"
video.play()
}
Component.onDestruction: {
disconnectFromHost()
}
function getState() {
switch (state) {
case MqttClient.Disconnected:
return "red"
case MqttClient.Connecting:
return "yellow"
case MqttClient.Connected:
return "green"
default:
return "gray"
}
}
}
DoorOpener {
id: doorOpener
}
// caption
Label {
id: caption
text: "Heimdall"
font {
family: "Open Sans MS"
bold: true
capitalization: Font.SmallCaps
pointSize: 14
}
anchors {
top: parent.top
topMargin: 10
horizontalCenter: parent.horizontalCenter
}
}
// webcam stream
Video {
id: video
objectName: "vplayer"
width: parent.width - 20
height: 200
autoPlay: client.connected
source: "rtsp://192.168.2.189:8554/mystream" // TODO
onPlaying: vplaceholder.visible = false
Image {
id: vplaceholder
width: parent.width
height: parent.height
source: "qrc:/res/test_picture.png"
}
anchors {
top: caption.bottom
topMargin: 10
horizontalCenter: parent.horizontalCenter
}
onErrorChanged: {
console.log("error: " + video.errorString)
}
MouseArea {
anchors.fill: parent
onClicked: {
video.muted = !video.muted
}
}
focus: true
Image {
id: muteIndicator
source: "qrc:/res/mute_white.png"
width: 64
height: width
visible: video.muted
anchors.centerIn: parent
}
} // Video
// Buttons
Item {
width: parent.width
height: 50
anchors {
top: video.bottom
topMargin: 10
centerIn: parent
}
Button {
id: btnTalk
objectName: "btnTalk"
text: "Sprechen"
anchors.left: parent.left
anchors.leftMargin: 10
onClicked: {
bgrTalk.start()
}
Rectangle {
id: bgrect_talk
width: parent.width
height: parent.height
color: "white"
}
SequentialAnimation {
id: bgrTalk
PropertyAnimation {
target: bgrect_talk
property: "color"
to: "darkseagreen"
duration: 500
}
PropertyAnimation {
target: bgrect_talk
property: "color"
to: "white"
duration: 500
easing.type: Easing.InCirc
}
}
}
Button {
id: btnOpen
objectName: "btnOpen"
text: "Öffnen"
property var bgColor: "darkred"
anchors.right: parent.right
anchors.rightMargin: 10
onClicked: {
var opened = doorOpener.open()
if (opened) {
bgColor = "forestgreen"
}
bgrOpened.start()
}
Rectangle {
id: bgrect_open
width: parent.width
height: parent.height
color: "white"
}
SequentialAnimation {
id: bgrOpened
PropertyAnimation {
target: bgrect_open
property: "color"
to: btnOpen.bgColor
duration: 500
}
PropertyAnimation {
target: bgrect_open
property: "color"
to: "white"
duration: 500
easing.type: Easing.InCirc
}
}
}
}
Item {
anchors {
left: parent.left
leftMargin: 10
bottom: parent.bottom
bottomMargin: 10
}
width: parent.width - 20
height: 25
Rectangle {
id: stateIndicator
width: 75
height: 20
color: "gray"
Text {
id: stateIndicatorText
text: "?"
color: "white"
anchors.centerIn: parent
}
}
Button {
anchors.right: parent.right
text: "Reconnect"
onPressed: {
client.disconnectFromHost()
vplaceholder.visible = true
client.connectToHost()
}
width: 75
height: 20
}
}
}