summaryrefslogtreecommitdiffstats
path: root/tradeshow
diff options
context:
space:
mode:
authorAndrew O'Doherty <andrew.odoherty@qt.io>2018-04-27 12:37:48 +0200
committerAndrew O'Doherty <andrew.odoherty@qt.io>2018-05-31 13:25:24 +0000
commit22cdfdd27aaa885ac5b7b450c8fb82b87853250d (patch)
tree7ffcc3e15d66824386cbd78397f55cbc5d618018 /tradeshow
parentefba3d85875b20bd40e93bc6d94aca1531f25aae (diff)
add 3d alexa knx demo
The knx-demo directory needs to be divided into two sub-directories containing the alexa 3D demo and the 2d demo. Very large files used by the 3d demo are stored in https://git-lfs.qt.io/Gerrit/boot2qt-demos.git Change-Id: I55e4210e93fc9e017d85e163f13c0b04de96cff0 Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
Diffstat (limited to 'tradeshow')
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/demo.pro (renamed from tradeshow/knx-demo/demo.pro)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/demodatapoint.cpp (renamed from tradeshow/knx-demo/demodatapoint.cpp)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/demodatapoint.h (renamed from tradeshow/knx-demo/demodatapoint.h)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.cpp (renamed from tradeshow/knx-demo/etsdevelopmentboard.cpp)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.h (renamed from tradeshow/knx-demo/etsdevelopmentboard.h)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/ArrowDown.png (renamed from tradeshow/knx-demo/images/ArrowDown.png)bin1944 -> 1944 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/ArrowUp.png (renamed from tradeshow/knx-demo/images/ArrowUp.png)bin1955 -> 1955 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/Qt-logo-medium.png (renamed from tradeshow/knx-demo/images/Qt-logo-medium.png)bin2710 -> 2710 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/blind.png (renamed from tradeshow/knx-demo/images/blind.png)bin2511 -> 2511 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/blindCover.png (renamed from tradeshow/knx-demo/images/blindCover.png)bin700 -> 700 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/clock.png (renamed from tradeshow/knx-demo/images/clock.png)bin12589 -> 12589 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/e10View.png (renamed from tradeshow/knx-demo/images/e10View.png)bin4747 -> 4747 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/e1View.png (renamed from tradeshow/knx-demo/images/e1View.png)bin9036 -> 9036 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/e2View.png (renamed from tradeshow/knx-demo/images/e2View.png)bin6394 -> 6394 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/e3e4View.png (renamed from tradeshow/knx-demo/images/e3e4View.png)bin12311 -> 12311 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/e5e6View.png (renamed from tradeshow/knx-demo/images/e5e6View.png)bin2758 -> 2758 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/icon_light.png (renamed from tradeshow/knx-demo/images/icon_light.png)bin8745 -> 8745 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/off.png (renamed from tradeshow/knx-demo/images/off.png)bin10088 -> 10088 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/on_green.png (renamed from tradeshow/knx-demo/images/on_green.png)bin13368 -> 13368 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/on_orange.png (renamed from tradeshow/knx-demo/images/on_orange.png)bin12787 -> 12787 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/quit_icon.png (renamed from tradeshow/knx-demo/images/quit_icon.png)bin2417 -> 2417 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/rainbow.png (renamed from tradeshow/knx-demo/images/rainbow.png)bin1267 -> 1267 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/settings_icon.png (renamed from tradeshow/knx-demo/images/settings_icon.png)bin3002 -> 3002 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/stop_orange.png (renamed from tradeshow/knx-demo/images/stop_orange.png)bin16042 -> 16042 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/temperature_symbol.png (renamed from tradeshow/knx-demo/images/temperature_symbol.png)bin6750 -> 6750 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/images/topBar.png (renamed from tradeshow/knx-demo/images/topBar.png)bin357 -> 357 bytes
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/main.cpp (renamed from tradeshow/knx-demo/main.cpp)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/qml.qrc (renamed from tradeshow/knx-demo/qml.qrc)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.cpp (renamed from tradeshow/knx-demo/qmlknxdemo.cpp)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.h (renamed from tradeshow/knx-demo/qmlknxdemo.h)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/qtquickcontrols2.conf (renamed from tradeshow/knx-demo/qtquickcontrols2.conf)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/KnxBoardLayout.qml (renamed from tradeshow/knx-demo/ui/KnxBoardLayout.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/BlindSimulationView.qml (renamed from tradeshow/knx-demo/ui/components/BlindSimulationView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/ColorSlider.qml (renamed from tradeshow/knx-demo/ui/components/ColorSlider.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E10LedView.qml (renamed from tradeshow/knx-demo/ui/components/E10LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E11LedView.qml (renamed from tradeshow/knx-demo/ui/components/E11LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E12LedView.qml (renamed from tradeshow/knx-demo/ui/components/E12LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E13LedView.qml (renamed from tradeshow/knx-demo/ui/components/E13LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E14LedView.qml (renamed from tradeshow/knx-demo/ui/components/E14LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E1LedView.qml (renamed from tradeshow/knx-demo/ui/components/E1LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E2LedView.qml (renamed from tradeshow/knx-demo/ui/components/E2LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E3E4LedView.qml (renamed from tradeshow/knx-demo/ui/components/E3E4LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E5E6LedView.qml (renamed from tradeshow/knx-demo/ui/components/E5E6LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E7E8LedView.qml (renamed from tradeshow/knx-demo/ui/components/E7E8LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/E9LedView.qml (renamed from tradeshow/knx-demo/ui/components/E9LedView.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/components/KnxSwitch.qml (renamed from tradeshow/knx-demo/ui/components/KnxSwitch.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/ui/main.qml (renamed from tradeshow/knx-demo/ui/main.qml)0
-rw-r--r--tradeshow/knx-demo/2d-knx-demo/utils.h (renamed from tradeshow/knx-demo/utils.h)0
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.ico3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.pro73
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.qrc54
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.cpp246
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.h161
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.cpp136
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.h107
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.cpp143
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.h118
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/images/home-automation-demo.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/main.cpp230
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.cpp65
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.h68
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.cpp281
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.h92
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/HomeView.qml401
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSlider.qml73
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSwitch.qml122
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/MainMenu.qml80
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/RoomLabel.qml88
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SliderControl.qml150
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SplashScreen.qml62
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/TempSlider.qml113
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/main.qml106
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/QtSymbol.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_light.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_temp.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/Style.qml68
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/qmldir2
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp362
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.h142
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.cpp459
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.h115
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.cpp367
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.h130
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.cpp237
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.h86
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/readme.md15
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/House.import114
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/maps/houseShape.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Ground.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BathRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BedRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_DressRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Entrance.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_LivingRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_MasterBedroom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Sauna.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_StoreRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Toilet.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Windows.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/house1.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/roof1.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/houseStudio.uip3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BathroomLightmap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BedRoomLightmap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/EntranceLightmap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Ground.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseGroundOpacitymap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.jpg3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/LivingRoomLightMap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/MasterBedroomLightmap.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/OpenfootageNET_Pinzgau-512.hdr3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Roof.png3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/HeatAreas.import76
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BathRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BedRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_DressRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_LivingRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_MasterBedroom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Sauna.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_StoreRoom.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Toilet.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/Heat_Entrance HeatAreas.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/House.import39
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Ground.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/House.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Roof.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Windows.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/Light/Light.import9
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/RoomLights.import46
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BathroomLightmap.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BedroomLightmap.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/EntranceLightmap.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/LivingroomLightMap.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/MasterbedroomLightmap.mesh3
-rw-r--r--tradeshow/knx-demo/3d-Alexa-knx-demo/utils.h111
136 files changed, 5494 insertions, 0 deletions
diff --git a/tradeshow/knx-demo/demo.pro b/tradeshow/knx-demo/2d-knx-demo/demo.pro
index f5473de..f5473de 100644
--- a/tradeshow/knx-demo/demo.pro
+++ b/tradeshow/knx-demo/2d-knx-demo/demo.pro
diff --git a/tradeshow/knx-demo/demodatapoint.cpp b/tradeshow/knx-demo/2d-knx-demo/demodatapoint.cpp
index 710a6e0..710a6e0 100644
--- a/tradeshow/knx-demo/demodatapoint.cpp
+++ b/tradeshow/knx-demo/2d-knx-demo/demodatapoint.cpp
diff --git a/tradeshow/knx-demo/demodatapoint.h b/tradeshow/knx-demo/2d-knx-demo/demodatapoint.h
index 1810203..1810203 100644
--- a/tradeshow/knx-demo/demodatapoint.h
+++ b/tradeshow/knx-demo/2d-knx-demo/demodatapoint.h
diff --git a/tradeshow/knx-demo/etsdevelopmentboard.cpp b/tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.cpp
index c8a3ccb..c8a3ccb 100644
--- a/tradeshow/knx-demo/etsdevelopmentboard.cpp
+++ b/tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.cpp
diff --git a/tradeshow/knx-demo/etsdevelopmentboard.h b/tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.h
index e95c701..e95c701 100644
--- a/tradeshow/knx-demo/etsdevelopmentboard.h
+++ b/tradeshow/knx-demo/2d-knx-demo/etsdevelopmentboard.h
diff --git a/tradeshow/knx-demo/images/ArrowDown.png b/tradeshow/knx-demo/2d-knx-demo/images/ArrowDown.png
index 0606ccc..0606ccc 100644
--- a/tradeshow/knx-demo/images/ArrowDown.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/ArrowDown.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/ArrowUp.png b/tradeshow/knx-demo/2d-knx-demo/images/ArrowUp.png
index ad4fb59..ad4fb59 100644
--- a/tradeshow/knx-demo/images/ArrowUp.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/ArrowUp.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/Qt-logo-medium.png b/tradeshow/knx-demo/2d-knx-demo/images/Qt-logo-medium.png
index 7d42da6..7d42da6 100644
--- a/tradeshow/knx-demo/images/Qt-logo-medium.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/Qt-logo-medium.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/blind.png b/tradeshow/knx-demo/2d-knx-demo/images/blind.png
index fc78346..fc78346 100644
--- a/tradeshow/knx-demo/images/blind.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/blind.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/blindCover.png b/tradeshow/knx-demo/2d-knx-demo/images/blindCover.png
index ae7c752..ae7c752 100644
--- a/tradeshow/knx-demo/images/blindCover.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/blindCover.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/clock.png b/tradeshow/knx-demo/2d-knx-demo/images/clock.png
index f5fb2af..f5fb2af 100644
--- a/tradeshow/knx-demo/images/clock.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/clock.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/e10View.png b/tradeshow/knx-demo/2d-knx-demo/images/e10View.png
index b3df098..b3df098 100644
--- a/tradeshow/knx-demo/images/e10View.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/e10View.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/e1View.png b/tradeshow/knx-demo/2d-knx-demo/images/e1View.png
index 99b8804..99b8804 100644
--- a/tradeshow/knx-demo/images/e1View.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/e1View.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/e2View.png b/tradeshow/knx-demo/2d-knx-demo/images/e2View.png
index 578a2a1..578a2a1 100644
--- a/tradeshow/knx-demo/images/e2View.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/e2View.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/e3e4View.png b/tradeshow/knx-demo/2d-knx-demo/images/e3e4View.png
index d8e97b9..d8e97b9 100644
--- a/tradeshow/knx-demo/images/e3e4View.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/e3e4View.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/e5e6View.png b/tradeshow/knx-demo/2d-knx-demo/images/e5e6View.png
index e2e81fd..e2e81fd 100644
--- a/tradeshow/knx-demo/images/e5e6View.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/e5e6View.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/icon_light.png b/tradeshow/knx-demo/2d-knx-demo/images/icon_light.png
index e59ef79..e59ef79 100644
--- a/tradeshow/knx-demo/images/icon_light.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/icon_light.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/off.png b/tradeshow/knx-demo/2d-knx-demo/images/off.png
index ee01cf7..ee01cf7 100644
--- a/tradeshow/knx-demo/images/off.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/off.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/on_green.png b/tradeshow/knx-demo/2d-knx-demo/images/on_green.png
index 3b7e47e..3b7e47e 100644
--- a/tradeshow/knx-demo/images/on_green.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/on_green.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/on_orange.png b/tradeshow/knx-demo/2d-knx-demo/images/on_orange.png
index ebc0044..ebc0044 100644
--- a/tradeshow/knx-demo/images/on_orange.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/on_orange.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/quit_icon.png b/tradeshow/knx-demo/2d-knx-demo/images/quit_icon.png
index 7b022a3..7b022a3 100644
--- a/tradeshow/knx-demo/images/quit_icon.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/quit_icon.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/rainbow.png b/tradeshow/knx-demo/2d-knx-demo/images/rainbow.png
index b426d37..b426d37 100644
--- a/tradeshow/knx-demo/images/rainbow.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/rainbow.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/settings_icon.png b/tradeshow/knx-demo/2d-knx-demo/images/settings_icon.png
index c0ccb48..c0ccb48 100644
--- a/tradeshow/knx-demo/images/settings_icon.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/settings_icon.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/stop_orange.png b/tradeshow/knx-demo/2d-knx-demo/images/stop_orange.png
index aea256b..aea256b 100644
--- a/tradeshow/knx-demo/images/stop_orange.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/stop_orange.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/temperature_symbol.png b/tradeshow/knx-demo/2d-knx-demo/images/temperature_symbol.png
index cad112f..cad112f 100644
--- a/tradeshow/knx-demo/images/temperature_symbol.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/temperature_symbol.png
Binary files differ
diff --git a/tradeshow/knx-demo/images/topBar.png b/tradeshow/knx-demo/2d-knx-demo/images/topBar.png
index ba4cb1c..ba4cb1c 100644
--- a/tradeshow/knx-demo/images/topBar.png
+++ b/tradeshow/knx-demo/2d-knx-demo/images/topBar.png
Binary files differ
diff --git a/tradeshow/knx-demo/main.cpp b/tradeshow/knx-demo/2d-knx-demo/main.cpp
index f1c5fc5..f1c5fc5 100644
--- a/tradeshow/knx-demo/main.cpp
+++ b/tradeshow/knx-demo/2d-knx-demo/main.cpp
diff --git a/tradeshow/knx-demo/qml.qrc b/tradeshow/knx-demo/2d-knx-demo/qml.qrc
index 850bc0d..850bc0d 100644
--- a/tradeshow/knx-demo/qml.qrc
+++ b/tradeshow/knx-demo/2d-knx-demo/qml.qrc
diff --git a/tradeshow/knx-demo/qmlknxdemo.cpp b/tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.cpp
index 4215246..4215246 100644
--- a/tradeshow/knx-demo/qmlknxdemo.cpp
+++ b/tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.cpp
diff --git a/tradeshow/knx-demo/qmlknxdemo.h b/tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.h
index dd9b037..dd9b037 100644
--- a/tradeshow/knx-demo/qmlknxdemo.h
+++ b/tradeshow/knx-demo/2d-knx-demo/qmlknxdemo.h
diff --git a/tradeshow/knx-demo/qtquickcontrols2.conf b/tradeshow/knx-demo/2d-knx-demo/qtquickcontrols2.conf
index 1764b16..1764b16 100644
--- a/tradeshow/knx-demo/qtquickcontrols2.conf
+++ b/tradeshow/knx-demo/2d-knx-demo/qtquickcontrols2.conf
diff --git a/tradeshow/knx-demo/ui/KnxBoardLayout.qml b/tradeshow/knx-demo/2d-knx-demo/ui/KnxBoardLayout.qml
index 5fd5d3a..5fd5d3a 100644
--- a/tradeshow/knx-demo/ui/KnxBoardLayout.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/KnxBoardLayout.qml
diff --git a/tradeshow/knx-demo/ui/components/BlindSimulationView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/BlindSimulationView.qml
index 11a0fbd..11a0fbd 100644
--- a/tradeshow/knx-demo/ui/components/BlindSimulationView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/BlindSimulationView.qml
diff --git a/tradeshow/knx-demo/ui/components/ColorSlider.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/ColorSlider.qml
index cf507c7..cf507c7 100644
--- a/tradeshow/knx-demo/ui/components/ColorSlider.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/ColorSlider.qml
diff --git a/tradeshow/knx-demo/ui/components/E10LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E10LedView.qml
index 79345df..79345df 100644
--- a/tradeshow/knx-demo/ui/components/E10LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E10LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E11LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E11LedView.qml
index fd0eee7..fd0eee7 100644
--- a/tradeshow/knx-demo/ui/components/E11LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E11LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E12LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E12LedView.qml
index 4b91eab..4b91eab 100644
--- a/tradeshow/knx-demo/ui/components/E12LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E12LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E13LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E13LedView.qml
index 9d0e937..9d0e937 100644
--- a/tradeshow/knx-demo/ui/components/E13LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E13LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E14LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E14LedView.qml
index 85987d8..85987d8 100644
--- a/tradeshow/knx-demo/ui/components/E14LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E14LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E1LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E1LedView.qml
index 6b676c2..6b676c2 100644
--- a/tradeshow/knx-demo/ui/components/E1LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E1LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E2LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E2LedView.qml
index f844141..f844141 100644
--- a/tradeshow/knx-demo/ui/components/E2LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E2LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E3E4LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E3E4LedView.qml
index cc0f4f8..cc0f4f8 100644
--- a/tradeshow/knx-demo/ui/components/E3E4LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E3E4LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E5E6LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E5E6LedView.qml
index 564c050..564c050 100644
--- a/tradeshow/knx-demo/ui/components/E5E6LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E5E6LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E7E8LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E7E8LedView.qml
index 92be92f..92be92f 100644
--- a/tradeshow/knx-demo/ui/components/E7E8LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E7E8LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/E9LedView.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/E9LedView.qml
index e384ea7..e384ea7 100644
--- a/tradeshow/knx-demo/ui/components/E9LedView.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/E9LedView.qml
diff --git a/tradeshow/knx-demo/ui/components/KnxSwitch.qml b/tradeshow/knx-demo/2d-knx-demo/ui/components/KnxSwitch.qml
index f56bec8..f56bec8 100644
--- a/tradeshow/knx-demo/ui/components/KnxSwitch.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/components/KnxSwitch.qml
diff --git a/tradeshow/knx-demo/ui/main.qml b/tradeshow/knx-demo/2d-knx-demo/ui/main.qml
index 92399a8..92399a8 100644
--- a/tradeshow/knx-demo/ui/main.qml
+++ b/tradeshow/knx-demo/2d-knx-demo/ui/main.qml
diff --git a/tradeshow/knx-demo/utils.h b/tradeshow/knx-demo/2d-knx-demo/utils.h
index 16c0877..16c0877 100644
--- a/tradeshow/knx-demo/utils.h
+++ b/tradeshow/knx-demo/2d-knx-demo/utils.h
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.ico b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.ico
new file mode 100644
index 0000000..41756e8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.ico
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5585eea1337687eaefa2223edded680963f45bee56a971c94d11603ee4aaf696
+size 108337
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.pro b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.pro
new file mode 100644
index 0000000..e70f4e4
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.pro
@@ -0,0 +1,73 @@
+TEMPLATE = app
+
+# Control KNX board with the demo
+CONFIG += KNX_BOARD ALEXA_WEMO
+#CONFIG += ALEXA_WEMO
+
+KNX_BOARD {
+ requires(qtHaveModule(knx))
+ requires(qtHaveModule(network))
+ DEFINES += KNX_BACKEND
+
+ QT += knx
+ CONFIG += c++11
+}
+
+QT += qml quick
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+SOURCES += main.cpp \
+ housemodel.cpp
+
+HEADERS += \
+ housemodel.h
+
+RESOURCES += HomeAutom.qrc
+
+OTHER_FILES += qml/HomeAutom/*
+
+RC_ICONS += HomeAutom.ico
+
+KNX_BOARD {
+ SOURCES += \
+ qmlknxdemo.cpp \
+ etsdevelopmentboard.cpp \
+ demodatapoint.cpp
+
+ HEADERS += \
+ qmlknxdemo.h \
+ demodatapoint.h \
+ utils.h \
+ etsdevelopmentboard.h
+}
+
+ALEXA_WEMO {
+ SOURCES += \
+ qupnpservice.cpp \
+ qupnprootdevice.cpp \
+ qvirtualbelkinwemo.cpp \
+ qminimalhttpserver.cpp
+
+ HEADERS += \
+ qupnpservice.h \
+ qupnprootdevice.h \
+ qvirtualbelkinwemo.h \
+ qminimalhttpserver.h
+
+ QT += xml
+}
+
+QML_IMPORT_PATH = $$PWD/qml/imports
+
+DISTFILES += \
+ android/AndroidManifest.xml \
+ android/gradle/wrapper/gradle-wrapper.jar \
+ android/gradlew \
+ android/res/values/libs.xml \
+ android/build.gradle \
+ android/gradle/wrapper/gradle-wrapper.properties \
+ android/gradlew.bat
+
+#ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.qrc b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.qrc
new file mode 100644
index 0000000..ca9c557
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/HomeAutom.qrc
@@ -0,0 +1,54 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/images/QtSymbol.png</file>
+ <file alias="main.qml">qml/HomeAutom/main.qml</file>
+ <file alias="HomeView.qml">qml/HomeAutom/HomeView.qml</file>
+ <file alias="SplashScreen.qml">qml/HomeAutom/SplashScreen.qml</file>
+ <file alias="MainMenu.qml">qml/HomeAutom/MainMenu.qml</file>
+ <file alias="TempSlider.qml">qml/HomeAutom/TempSlider.qml</file>
+ <file alias="SliderControl.qml">qml/HomeAutom/SliderControl.qml</file>
+ <file alias="LightSlider.qml">qml/HomeAutom/LightSlider.qml</file>
+ <file alias="RoomLabel.qml">qml/HomeAutom/RoomLabel.qml</file>
+ <file alias="LightSwitch.qml">qml/HomeAutom/LightSwitch.qml</file>
+ <file>uip/houseStudio.uip</file>
+ <file>uip/maps/Ground.png</file>
+ <file>uip/maps/HouseGroundOpacitymap.png</file>
+ <file>uip/maps/HouseTexture.png</file>
+ <file>uip/maps/OpenfootageNET_Pinzgau-512.hdr</file>
+ <file>uip/maps/Roof.png</file>
+ <file>uip/models/HeatAreas/meshes/Heat_Entrance HeatAreas.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_BathRoom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_BedRoom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_DressRoom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_LivingRoom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_MasterBedroom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_Sauna.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_StoreRoom.mesh</file>
+ <file>uip/models/HeatAreas/meshes/HeatAreas Heat_Toilet.mesh</file>
+ <file>uip/models/HeatAreas/HeatAreas.import</file>
+ <file>uip/models/House/meshes/Ground.mesh</file>
+ <file>uip/models/House/meshes/House.mesh</file>
+ <file>uip/models/House/meshes/Roof.mesh</file>
+ <file>uip/models/House/meshes/Windows.mesh</file>
+ <file>uip/models/House/House.import</file>
+ <file>uip/models/Light/Light.import</file>
+ <file>uip/House/meshes/house1.mesh</file>
+ <file>uip/House/meshes/roof1.mesh</file>
+ <file>uip/maps/BathroomLightmap.png</file>
+ <file>uip/maps/BedRoomLightmap.png</file>
+ <file>uip/maps/EntranceLightmap.png</file>
+ <file>uip/maps/LivingRoomLightMap.png</file>
+ <file>uip/maps/MasterBedroomLightmap.png</file>
+ <file>uip/models/RoomLights/RoomLights.import</file>
+ <file>uip/models/RoomLights/meshes/BathroomLightmap.mesh</file>
+ <file>uip/models/RoomLights/meshes/BedroomLightmap.mesh</file>
+ <file>uip/models/RoomLights/meshes/EntranceLightmap.mesh</file>
+ <file>uip/models/RoomLights/meshes/LivingroomLightMap.mesh</file>
+ <file>uip/models/RoomLights/meshes/MasterbedroomLightmap.mesh</file>
+ <file>qml/images/icon_light.png</file>
+ <file>qml/images/icon_temp.png</file>
+ <file>uip/maps/HouseTexture.jpg</file>
+ <file>qml/imports/Style/qmldir</file>
+ <file>qml/imports/Style/Style.qml</file>
+ </qresource>
+</RCC>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.cpp
new file mode 100644
index 0000000..95c82a8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "demodatapoint.h"
+
+#include <QtCore/QTimer>
+#include <QtGui/QColor>
+#include <QtKnx/QKnx1Bit>
+#include <QtKnx/QKnxNpdu>
+#include <QtKnx/QKnxNpduFactory>
+#include <QtKnx/QKnxTunnelFrame>
+
+const QByteArray DemoDataPoint::BytesOn = QByteArray::fromHex("0x1");
+const QByteArray DemoDataPoint::BytesOff = QByteArray::fromHex("0x0");
+
+bool DemoSwitchDataPoint::updateDataPointState(const QKnxTunnelFrame &frame)
+{
+ auto str = frame.serviceInformation().bytes().toHex();
+ m_state = (str[str.size() - 1] == '1');
+ return true;
+}
+
+void DemoSwitchDataPoint::uiToggle()
+{
+ m_state = !m_state;
+}
+
+bool DemoSwitchDataPoint::isOn() const
+{
+ return m_state;
+}
+
+QByteArray DemoSwitchDataPoint::bytes() const
+{
+ if (m_state)
+ return DemoDataPoint::BytesOn;
+ return DemoDataPoint::BytesOff;
+}
+
+bool DemoColorLed::updateDataPointState(const QKnxTunnelFrame &frame)
+{
+ bool notifyUI = false;
+ numMsgConfirmation++;
+ if (frame.messageCode() == QKnxCemiFrame::MessageCode::DataConfirmation) {
+ // response to request from UI
+ // wait for three color confirmation to signal UI
+ if (numMsgConfirmation == 3)
+ notifyUI = true;
+ } else if (frame.messageCode() == QKnxCemiFrame::MessageCode::DataIndication) {
+ // response to request from Board
+ notifyUI = true;
+ }
+
+ QKnxSwitch dpt;
+ dpt.setBytes(frame.npdu().data(), 0, 1);
+ int value = (dpt.value() == QKnxSwitch::State::On ? 255 : 0);
+
+ auto dstAddress = frame.destinationAddress();
+ if (dstAddress == QKnxAddress::createGroup(0, 0, 12))
+ m_stateColor.setRed(value);
+
+ else if (dstAddress == QKnxAddress::createGroup(0, 0, 13))
+ m_stateColor.setGreen(value);
+
+ else if (dstAddress == QKnxAddress::createGroup(0, 0, 14))
+ m_stateColor.setBlue(value);
+
+ if (notifyUI) {
+ numMsgConfirmation = 0;
+ emit colorChange(m_stateColor);
+ }
+ return false;
+}
+
+QByteArray DemoColorLed::redBytes() const
+{
+ if (m_stateColor.red() > 0)
+ return DemoDataPoint::BytesOn;
+ return DemoDataPoint::BytesOff;
+}
+
+QByteArray DemoColorLed::greenBytes() const
+{
+ if (m_stateColor.green() > 0)
+ return DemoDataPoint::BytesOn;
+ return DemoDataPoint::BytesOff;
+}
+
+QByteArray DemoColorLed::blueBytes() const
+{
+ if (m_stateColor.blue() > 0)
+ return DemoDataPoint::BytesOn;
+ return DemoDataPoint::BytesOff;
+}
+
+QColor DemoColorLed::currentColor() const
+{
+ return m_stateColor;
+}
+
+void DemoColorLed::setCurrentColor(QColor color)
+{
+ m_stateColor = color;
+}
+
+bool DemoColorLed::isOn() const
+{
+ return (m_stateColor != Qt::black);
+}
+
+bool DemoRockerDataPoint::updateDataPointState(const QKnxTunnelFrame &frame)
+{
+ auto str = frame.serviceInformation().bytes().toHex();
+ QString s = str.mid(20, 4);
+ bool ok;
+ setPosition(s.toInt(&ok, 16));
+ emit rockerChange(m_position);
+ return false;
+}
+
+void DemoBlindDataPoint::chooseTimeoutHandle(bool blindUp)
+{
+ if (blindUp) {
+ disconnect(&m_timer, &QTimer::timeout, this, &DemoBlindDataPoint::moveBlindDown);
+ connect(&m_timer, &QTimer::timeout, this, &DemoBlindDataPoint::moveBlindUp);
+ } else {
+ disconnect(&m_timer, &QTimer::timeout, this, &DemoBlindDataPoint::moveBlindUp);
+ connect(&m_timer, &QTimer::timeout, this, &DemoBlindDataPoint::moveBlindDown);
+ }
+}
+
+bool DemoBlindDataPoint::updateDataPointState(const QKnxTunnelFrame &frame)
+{
+ auto npdu = frame.npdu();
+ if (frame.destinationAddress().toString() == "1/0/0") {
+ stopBlind();
+
+ QKnx1Bit dpt;
+ dpt.setBytes(frame.npdu().data(), 0, 1);
+
+ chooseTimeoutHandle(dpt.bit());
+ reenableTimer();
+ } else if (frame.destinationAddress().toString() == "1/1/0") {
+ stopBlind();
+ }
+ return false;
+}
+
+void DemoBlindDataPoint::reenableTimer()
+{
+ if (!m_timer.isActive())
+ m_timer.start(50);
+}
+
+void DemoBlindDataPoint::moveBlindUp()
+{
+ if (m_position == 70) {
+ stopBlind();
+ emit blindFullyUp();
+ return;
+ }
+ ++m_position;
+ emit blindChange(m_position);
+}
+
+void DemoBlindDataPoint::moveBlindDown()
+{
+ if (m_position > 0) {
+ --m_position;
+ emit blindChange(m_position);
+ return;
+ }
+ stopBlind();
+ emit blindFullyDown();
+}
+
+void DemoBlindDataPoint::stopBlind()
+{
+ if (m_timer.isActive())
+ m_timer.stop();
+}
+
+QByteArray DemoBlindDataPoint::moveUpBytes() const
+{
+ // send a 0 to move up
+ return DemoDataPoint::BytesOff;
+}
+
+QByteArray DemoBlindDataPoint::moveDownBytes() const
+{
+ // send a 1 to move down
+ return DemoDataPoint::BytesOn;
+}
+
+QByteArray DemoBlindDataPoint::stopBytes() const
+{
+ // send a 1 to stop
+ return DemoDataPoint::BytesOn;
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.h
new file mode 100644
index 0000000..5c465a2
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/demodatapoint.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEMODATAPOINT_H
+#define DEMODATAPOINT_H
+
+#include <QtCore/QTimer>
+#include <QtGui/QColor>
+#include <QtKnx/QKnxTunnelFrame>
+
+class DemoDataPoint
+{
+public:
+ virtual ~DemoDataPoint() = default;
+
+ virtual QByteArray bytes() const { return QByteArray(); }
+ virtual bool updateDataPointState(const QKnxTunnelFrame &frame) = 0;
+
+ int position() const { return m_position; }
+ void setPosition(int pos) { m_position = pos; }
+
+protected:
+ int m_position { 0 };
+
+ static const QByteArray BytesOn;
+ static const QByteArray BytesOff;
+};
+
+class DemoSwitchDataPoint : public DemoDataPoint
+{
+public:
+ DemoSwitchDataPoint() = default;
+ ~DemoSwitchDataPoint() override = default;
+
+ QByteArray bytes() const override;
+ bool updateDataPointState(const QKnxTunnelFrame &frame) override;
+
+ void uiToggle();
+ bool isOn() const;
+
+private:
+ bool m_state;
+};
+
+class DemoColorLed : public QObject, public DemoDataPoint
+{
+ Q_OBJECT
+
+public:
+ DemoColorLed() = default;
+ ~DemoColorLed() override = default;
+
+ bool updateDataPointState(const QKnxTunnelFrame &frame) override;
+
+ QColor currentColor() const;
+ void setCurrentColor(QColor color);
+
+ QByteArray redBytes() const;
+ QByteArray greenBytes() const;
+ QByteArray blueBytes() const;
+
+ bool isOn() const;
+
+Q_SIGNALS:
+ void colorChange(QColor color);
+
+private:
+ QColor m_stateColor;
+ quint8 numMsgConfirmation { 0 };
+};
+
+class DemoRockerDataPoint : public QObject, public DemoDataPoint
+{
+ Q_OBJECT
+public:
+ DemoRockerDataPoint() = default;
+ virtual ~DemoRockerDataPoint() override = default;
+
+ bool updateDataPointState(const QKnxTunnelFrame &frame) override;
+
+Q_SIGNALS:
+ void rockerChange(int position);
+};
+
+class DemoBlindDataPoint : public QObject, public DemoDataPoint
+{
+ Q_OBJECT
+public:
+ DemoBlindDataPoint() = default;
+ ~DemoBlindDataPoint() override = default;
+
+ bool updateDataPointState(const QKnxTunnelFrame &frame) override;
+
+ QByteArray moveUpBytes() const;
+ QByteArray moveDownBytes() const;
+ QByteArray stopBytes() const;
+
+public slots:
+ void moveBlindUp();
+ void moveBlindDown();
+ void stopBlind();
+
+Q_SIGNALS:
+ void blindChange(int position);
+ void blindFullyUp();
+ void blindFullyDown();
+
+private:
+ void chooseTimeoutHandle(bool blindUp);
+ void reenableTimer();
+ QTimer m_timer;
+};
+
+#endif // DEMODATAPOINT_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.cpp
new file mode 100644
index 0000000..b963fec
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "etsdevelopmentboard.h"
+#include "demodatapoint.h"
+
+EtsDevelopmentBoard::EtsDevelopmentBoard()
+{
+ //e1-e6
+ quint8 indexMapKey = 1;
+ for (quint8 i = 1; i < 7 ; ++i) // small white leds
+ addDevice(indexMapKey++, 0, 0, i, QSharedPointer<DemoSwitchDataPoint>::create());
+ //e7-e8
+ auto blindDataPoint = QSharedPointer<DemoBlindDataPoint>::create();
+ addDevice(7, 1, 0, 0, blindDataPoint); // blind up/down
+ //skip e8 (because e7 and e8 are the same)
+ addDevice(8, 1, 0, 0, blindDataPoint); // blind up/down
+ //indexMapKey++;
+ //e9 red led
+ addDevice(9, 0, 0, 7, QSharedPointer<DemoSwitchDataPoint>::create());
+ //e10 red led
+ addDevice(10, 0, 0, 8, QSharedPointer<DemoSwitchDataPoint>::create());
+ //e11 red led
+ addDevice(11, 0, 0, 9, QSharedPointer<DemoSwitchDataPoint>::create());
+ //e12 red led
+ addDevice(12, 0, 0, 10, QSharedPointer<DemoSwitchDataPoint>::create());
+ // e13
+ auto colorLed = QSharedPointer<DemoColorLed>::create();
+ addDevice(13, 0, 0, 12, colorLed); // left Red
+ addDevice(13, 0, 0, 13, colorLed); // left Green
+ addDevice(13, 0, 0, 14, colorLed); // left Blue
+ // e14
+ addDevice(14, 0, 0, 11, QSharedPointer<DemoSwitchDataPoint>::create()); // right white
+ addDevice(15, 2, 0, 0, QSharedPointer<DemoRockerDataPoint>::create()); // Rocker
+ // e16 turn off blind up/down
+ addDevice(16, 1, 1, 0, blindDataPoint);
+}
+
+DemoDataPoint *EtsDevelopmentBoard::getGroupObject(int idx) const
+{
+ return m_dataPoints.value(idx).dpt.data();
+}
+
+DemoDataPoint *EtsDevelopmentBoard::getGroupObject(const QKnxAddress &address) const
+{
+ return getGroupObject(getIndex(address));
+}
+
+int EtsDevelopmentBoard::getIndex(const QKnxAddress &address) const
+{
+ return m_addressToDataPoints.value(address);
+}
+
+QKnxAddress EtsDevelopmentBoard::getAddress(int idx) const
+{
+ return m_dataPoints.value(idx).address;
+}
+
+bool EtsDevelopmentBoard::exists(const QKnxAddress &address) const
+{
+ return m_addressToDataPoints.contains(address);
+}
+
+DemoRockerDataPoint *EtsDevelopmentBoard::getRocker() const
+{
+ return static_cast<DemoRockerDataPoint *>(getGroupObject(DeviceNumbers::ROCKER));
+}
+
+DemoBlindDataPoint *EtsDevelopmentBoard::getBlind() const
+{
+ return static_cast<DemoBlindDataPoint *>(getGroupObject(DeviceNumbers::E7));
+}
+
+DemoColorLed *EtsDevelopmentBoard::getColorLed() const
+{
+ return static_cast<DemoColorLed *>(getGroupObject(DeviceNumbers::COLORLED));
+}
+
+void EtsDevelopmentBoard::addDevice(quint8 key, quint8 mainGroup, quint16 middleGroup,
+ quint8 subGroup, const QSharedPointer<DemoDataPoint> &dpt)
+{
+ auto address = QKnxAddress::createGroup(mainGroup, middleGroup, subGroup);
+
+ if (!m_dataPoints.contains(key))
+ m_dataPoints.insert(key, { address, dpt });
+
+ if (!m_addressToDataPoints.contains(address))
+ m_addressToDataPoints.insert(address, key);
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.h
new file mode 100644
index 0000000..7f6fbaa
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/etsdevelopmentboard.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ETSDEVELOPMENTBOARD_H
+#define ETSDEVELOPMENTBOARD_H
+
+#include "demodatapoint.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSharedPointer>
+#include <QtKnx/QKnxAddress>
+
+QT_BEGIN_NAMESPACE
+inline uint qHash(const QKnxAddress &key, uint seed)
+{
+ return qHash(key.toString(), seed);
+};
+QT_END_NAMESPACE
+
+class EtsDevelopmentBoard
+{
+public:
+ enum DeviceNumbers
+ {
+ E7 = 7, // blind control up
+ E8 = 8, // blind control down
+ COLORLED = 13,
+ MIDDLE_RIGHT = 14,
+ ROCKER = 15,
+ E16 = 16, // blind control down
+ };
+ EtsDevelopmentBoard();
+
+ DemoDataPoint *getGroupObject(int idx) const;
+ DemoDataPoint *getGroupObject(const QKnxAddress &address) const;
+
+ int getIndex(const QKnxAddress &address) const;
+ QKnxAddress getAddress(int idx) const;
+
+ bool exists(const QKnxAddress &address) const;
+
+ inline int size() const { return m_dataPoints.size(); };
+
+ DemoRockerDataPoint *getRocker() const;
+ DemoBlindDataPoint *getBlind() const;
+ DemoColorLed *getColorLed() const;
+
+private:
+ void addDevice(quint8 key, quint8 mainGroup, quint16 middleGroup, quint8 subGroup,
+ const QSharedPointer<DemoDataPoint> &dpt);
+
+ struct HashNode {
+ QKnxAddress address;
+ QSharedPointer<DemoDataPoint> dpt;
+ };
+ QHash<int, HashNode> m_dataPoints;
+ QHash<QKnxAddress, int> m_addressToDataPoints;
+};
+
+#endif
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.cpp
new file mode 100644
index 0000000..a768217
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "housemodel.h"
+
+HouseModel::HouseModel(QObject *parent) : QAbstractListModel(parent)
+{
+ generateRooms();
+}
+
+QHash<int, QByteArray> HouseModel::roleNames() const
+{
+ QHash<int, QByteArray> roles;
+ roles[NameRole] = "name";
+ roles[ItemRole] = "item";
+ roles[TemperatureRole] = "temperature";
+ roles[LightRole] = "light";
+ roles[XPosRole] = "xPos";
+ roles[YPosRole] = "yPos";
+
+ return roles;
+}
+
+QVariant HouseModel::data(const QModelIndex &index, int role) const
+{
+ if (role == NameRole)
+ return m_rooms.at(index.row()).getName();
+ else if (role == ItemRole)
+ return m_rooms.at(index.row()).getItem();
+ else if (role == TemperatureRole)
+ return m_rooms.at(index.row()).getTemperature();
+ else if (role == LightRole)
+ return m_rooms.at(index.row()).getLight();
+ else if (role == XPosRole)
+ return m_rooms.at(index.row()).getXPos();
+ else if (role == YPosRole)
+ return m_rooms.at(index.row()).getYPos();
+ else return QVariant();
+}
+
+bool HouseModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid()) {
+ if (role == TemperatureRole) {
+ m_rooms[index.row()].setTemperature(value.toInt());
+ emit dataChanged(index, index);
+ return true;
+ } else if (role == LightRole) {
+ m_rooms[index.row()].setLight(value.toDouble());
+ emit dataChanged(index, index);
+ return true;
+ }
+ }
+ return false;
+}
+
+int HouseModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_rooms.length();
+}
+
+bool HouseModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ Q_UNUSED(row)
+ Q_UNUSED(count)
+ Q_UNUSED(parent)
+ beginResetModel();
+ m_rooms.clear();
+ endResetModel();
+
+ return true;
+}
+
+void HouseModel::addRoom(const QString &name, const QString &item,
+ int temperature, double light, int xPos, int yPos)
+{
+ int row = m_rooms.size();
+ beginInsertRows(QModelIndex(), row, row);
+ m_rooms.insert(row, Room(name, item, temperature, light, xPos, yPos));
+ endInsertRows();
+}
+
+void HouseModel::generateRooms()
+{
+ removeRows(0, m_rooms.length());
+ // Position of labels is defined from the center point of window
+ addRoom(QStringLiteral("Living Room"), QStringLiteral("Livingroom"), 21, 0.8, 120, 200);
+ addRoom(QStringLiteral("Master Bedroom"), QStringLiteral("Masterbedroom"), 18, 0.8, -380, -290);
+ addRoom(QStringLiteral("Bedroom"), QStringLiteral("Bedroom"), 15, 0.0, -405, 170);
+ addRoom(QStringLiteral("Bath Room"), QStringLiteral("Bathroom"), 30, 1.0, -20, -320);
+#if !defined(KNX_BACKEND)
+ addRoom(QStringLiteral("Entrance"), QStringLiteral("Entrance"), 20, 0.6, -450, -70);
+#endif
+}
+
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.h
new file mode 100644
index 0000000..2ab134b
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/housemodel.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HOUSEMODEL_H
+#define HOUSEMODEL_H
+
+#include <QAbstractListModel>
+#include <QUrl>
+#include <QRect>
+
+class Room
+{
+public:
+ Room(const QString &name, const QString &item,
+ int temperature, double light, int x, int y)
+ : m_name(name)
+ , m_item(item)
+ , m_temperature(temperature)
+ , m_light(light)
+ , m_xPos(x)
+ , m_yPos(y) {}
+
+ QString getName() const { return m_name; }
+ QString getItem() const { return m_item; }
+ int getTemperature() const { return m_temperature; }
+ int getXPos() const { return m_xPos; }
+ int getYPos() const { return m_yPos; }
+ void setTemperature(int temperature) { m_temperature = temperature; }
+ double getLight() const { return m_light; }
+ void setLight(double light) { m_light = light; }
+ void setXPos(int x) { m_xPos = x; }
+ void setYPos(int y) { m_xPos = y; }
+
+private:
+ QString m_name;
+ QString m_item;
+ int m_temperature;
+ double m_light;
+ int m_xPos;
+ int m_yPos;
+};
+
+class HouseModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum RoomRoles {
+ NameRole = 0,
+ ItemRole,
+ TemperatureRole,
+ LightRole,
+ XPosRole,
+ YPosRole
+ };
+
+ HouseModel(QObject *parent = 0);
+ virtual QHash<int, QByteArray> roleNames() const;
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ void addRoom(const QString &name, const QString &item,
+ int temperature, double light, int xPos, int yPos);
+
+private:
+ void generateRooms();
+
+ QList<Room> m_rooms;
+};
+
+#endif // HOUSEMODEL_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/images/home-automation-demo.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/images/home-automation-demo.png
new file mode 100644
index 0000000..f6de49c
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/images/home-automation-demo.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0d9ac8b11e7dc4ed02a3199671477bc9d094be805d454b518a7594534613b41f
+size 3526749
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/main.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/main.cpp
new file mode 100644
index 0000000..a6239a6
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/main.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QGuiApplication>
+#include <QtCore/QDir>
+#include <QtCore/QVector>
+#include <QtQuick/QQuickView>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlContext>
+#include <QtGui/QScreen>
+#include <QtQml/QQmlPropertyMap>
+#include "housemodel.h"
+#if defined(KNX_BACKEND)
+#include "qmlknxdemo.h"
+#endif
+#define ALEXA_WEMO
+#if defined(ALEXA_WEMO)
+#include "qvirtualbelkinwemo.h"
+#endif
+
+// Uncomment for 1280x900 window
+//#define FIXEDWINDOW
+
+int applyFontRatio(const int value, const int ratioFont)
+{
+ return int(value * ratioFont);
+}
+
+int applyRatio(const int value, const int ratio)
+{
+ return qMax(2, int(value * ratio));
+}
+
+void setupWemoToKnx(QmlKnxDemo *m_knxBackend)
+{
+#if defined(ALEXA_WEMO)
+ static quint16 nextPort = 52000;
+ static QVector<QVirtualBelkinWeMo*> devices;
+ static QObject parent;
+ static QVirtualBelkinWeMo livingRoom(nullptr, "Livingroom");
+ static QVirtualBelkinWeMo masterbedroom(nullptr, "Master bedroom");
+ static QVirtualBelkinWeMo bedroom(nullptr, "Bedroom");
+ static QVirtualBelkinWeMo bathroom(nullptr, "Bathroom");
+ static QVirtualBelkinWeMo all(nullptr, "all");
+
+ devices.push_back(&livingRoom);
+ devices.push_back(&masterbedroom);
+ devices.push_back(&bedroom);
+ devices.push_back(&bathroom);
+ devices.push_back(&all);
+
+ livingRoom.startListening(nextPort++);
+ masterbedroom.startListening(nextPort++);
+ bedroom.startListening(nextPort++);
+ bathroom.startListening(nextPort++);
+ all.startListening(nextPort++);
+
+ qDebug () << "11111 Connecting services!";
+ for (int lightNum = 0; lightNum < devices.size(); ++lightNum) {
+ if (lightNum == (devices.size()-1))
+ {
+ QObject::connect(dynamic_cast<QUPnPBooleanService*>(devices[lightNum]->getService("")), &QUPnPBooleanService::stateChanged, [m_knxBackend](bool state){
+ for (int i = 1; i <= 4; ++i) {
+ if (m_knxBackend->getLightState(i) != state)
+ m_knxBackend->toggleLight(i);
+ }
+ m_knxBackend->changeRoom(0);
+ });
+
+ break;
+ }
+ QObject::connect(dynamic_cast<QUPnPBooleanService*>(devices[lightNum]->getService("")), &QUPnPBooleanService::stateChanged, [lightNum, m_knxBackend](bool state){
+ if (m_knxBackend->getLightState(lightNum+1) != state)
+ m_knxBackend->toggleLight(lightNum+1);
+ m_knxBackend->changeRoom(lightNum+1);
+ qDebug () << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Switching light! "<< lightNum+1 <<"state "<< (state ? "true":"false") << " light_state:" << m_knxBackend->getLightState(lightNum+1);
+ });
+ QObject::connect(dynamic_cast<QUPnPBooleanService*>(devices[lightNum]->getService("")), &QUPnPBooleanService::stateChangeFailed, [lightNum](){
+ qDebug () << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Switching light FAILEDDD! "<< lightNum+1;
+ });
+ }
+
+// QUPnPRootDevice rootdev(nullptr, "Qt UPnP to KNX Bridge");
+// QUPnPBooleanService *service = new QUPnPBooleanServiceProxy(&rootdev, dynamic_cast<QUPnPBooleanService*>(devices[0]->getService("")), "SwitchPower");
+// rootdev.addService(service);
+// rootdev.startListening(nextPort++);
+#else
+ Q_UNUSED(m_knxBackend)
+#endif
+ return;
+}
+
+
+int main(int argc, char *argv[])
+{
+////#if defined(Q_OS_MACOS)
+// QSurfaceFormat openGLFormat;
+// openGLFormat.setRenderableType(QSurfaceFormat::OpenGL);
+// openGLFormat.setProfile(QSurfaceFormat::CoreProfile);
+// openGLFormat.setMajorVersion(3);
+// openGLFormat.setMinorVersion(0);
+
+// //openGLFormat.setStencilBufferSize(8);
+// QSurfaceFormat::setDefaultFormat(openGLFormat);
+////#endif
+
+ QGuiApplication app(argc, argv);
+
+ // Define size variants for scaling
+ qreal refDpi = 96.;
+ qreal refWidth = 1280.;
+ qreal refHeight = 900.;
+ QRect rect = QGuiApplication::primaryScreen()->geometry();
+ qreal width = rect.width();
+ qreal height = rect.height();
+ qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
+ qreal widthRatio = width / refWidth;
+ qreal heightRatio = height / refHeight;
+ qreal ratioFont = qMin(height * dpi / (refDpi * refHeight), width * dpi / (refDpi * refWidth));
+ if (widthRatio < 1.)
+ widthRatio = 1;
+ if (heightRatio < 1.)
+ heightRatio = 1;
+ if (ratioFont < 1.)
+ ratioFont = 1;
+
+#ifdef FIXEDWINDOW
+ width = refWidth;
+ height = refHeight;
+ widthRatio = 1;
+ heightRatio = 1;
+ ratioFont = 1;
+#endif
+
+ QQmlPropertyMap sizesMap;
+ sizesMap.insert(QStringLiteral("screenHeight"), QVariant(height));
+ sizesMap.insert(QStringLiteral("screenWidth"), QVariant(width));
+ sizesMap.insert(QStringLiteral("fontSize"), QVariant(applyFontRatio(26, ratioFont)));
+ sizesMap.insert(QStringLiteral("controlHeight"), QVariant(applyFontRatio(64, ratioFont)));
+ sizesMap.insert(QStringLiteral("labelMouseMargin"), QVariant(applyRatio(20, widthRatio)));
+ sizesMap.insert(QStringLiteral("controlMargin"), QVariant(applyRatio(20, widthRatio)));
+ sizesMap.insert(QStringLiteral("controlBorderWidth"), QVariant(applyRatio(3, widthRatio)));
+ sizesMap.insert(QStringLiteral("sliderMaxWidth"), QVariant(applyRatio(300, widthRatio)));
+
+ QQuickView viewer;
+
+ viewer.engine()->addImportPath(QStringLiteral(":/qml/imports"));
+
+#ifndef Q_OS_ANDROID
+ // Hack to get self build working.
+ // Also needs the Qt3DStudio\bin directory in run environment path.
+ viewer.engine()->addImportPath(QStringLiteral("C:/Qt/Tools/Qt3DStudio/qml"));
+#endif
+
+#if defined(KNX_BACKEND)
+ qmlRegisterUncreatableType<QmlKnxDemo>("QmlKnxDemo", 1, 0, "QmlKnxDemo", "Not instantiated from QML");
+ QmlKnxDemo *m_knxBackend = new QmlKnxDemo;
+ viewer.engine()->rootContext()->setContextProperty(QStringLiteral("knxBackend"), m_knxBackend);
+ setupWemoToKnx(m_knxBackend);
+#else
+ viewer.engine()->rootContext()->setContextProperty(QStringLiteral("knxBackend"), nullptr);
+#endif
+
+ HouseModel *m_houseModel = new HouseModel;
+ viewer.engine()->rootContext()->setContextProperty(QStringLiteral("houseModel"), m_houseModel);
+
+ viewer.engine()->rootContext()->setContextProperty(QStringLiteral("sizesMap"), &sizesMap);
+ viewer.engine()->rootContext()->setContextProperty(QStringLiteral("heightRatio"), heightRatio);
+
+ viewer.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ viewer.setTitle(QStringLiteral("Qt 3D Studio Home Automation Demo"));
+ viewer.setResizeMode(QQuickView::SizeViewToRootObject);
+#ifdef FIXEDWINDOW
+ viewer.setMinimumSize(QSize(width, height));
+ viewer.setMaximumSize(QSize(width, height));
+ viewer.show();
+#else
+ viewer.showFullScreen();
+#endif
+
+ return app.exec();
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.cpp
new file mode 100644
index 0000000..629c8c7
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qalexatoknx.h"
+#include "mainwindow.h"
+
+QAlexaToKnx::QAlexaToKnx(MainWindow *target, QString name)
+ : QUPnPBooleanService(target)
+{
+ this->m_target = target;
+ this->identifier = name;
+}
+
+bool QAlexaToKnx::doSetState(bool state)
+{
+ m_target->append(identifier + " changed state to " + (state?"TRUE":"FALSE"));
+ return true;
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.h
new file mode 100644
index 0000000..2b3c9d1
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qalexatoknx.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QALEXATOKNX_H
+#define QALEXATOKNX_H
+
+#include "qupnpservice.h"
+
+class MainWindow;
+
+class QAlexaToKnx : public QUPnPBooleanService //QVirtualBelkinWeMo
+{
+ Q_OBJECT
+ MainWindow *m_target;
+public:
+ QAlexaToKnx(MainWindow *target, QString name);
+protected:
+ bool doSetState(bool state) override;
+};
+
+#endif // QALEXATOKNX_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.cpp
new file mode 100644
index 0000000..bef2161
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qminimalhttpserver.h"
+
+QMinimalHttpServer::QMinimalHttpServer(QObject *parent)
+ : QObject(parent)
+{
+ connect(&tcpServer, &QTcpServer::newConnection, this, &QMinimalHttpServer::onNewTcpConnection);
+}
+
+QMinimalHttpServer::~QMinimalHttpServer()
+{
+}
+
+void QMinimalHttpServer::addFile(QString filename, QByteArray &data, QString mimetype)
+{
+ filename = filename.toUpper(); // ensure case insensitivity
+ if (!filename.startsWith("/"))
+ filename = QStringLiteral("/") + filename;
+
+ httpFiles[filename] = data;
+ if (mimetype == "") {
+ QMimeDatabase db;
+ QList<QMimeType> types = db.mimeTypesForFileName(filename);
+ if (types.size() > 0)
+ mimetype = types[0].name();
+ }
+ httpFileMimeTypes[filename] = mimetype;
+}
+
+void QMinimalHttpServer::onNewTcpConnection()
+{
+ for (QTcpSocket* socket = tcpServer.nextPendingConnection(); socket; socket = tcpServer.nextPendingConnection()) {
+ #ifdef QT_DEBUG
+ qDebug() << "QMinimalHttpServer::connected " << socket->peerAddress().toString() << ":" << socket->peerPort();
+ #endif
+
+ connect(socket, &QTcpSocket::readyRead, [this, socket](){
+ this->onTcpDataReceived(socket);
+ });
+ connect(socket, &QTcpSocket::disconnected, [this, socket](){
+ #ifdef QT_DEBUG
+ qDebug() << "QMinimalHttpServer::disconnected " << socket->peerAddress().toString() << ":" << socket->peerPort();
+ #endif
+ //emit this->disconnected(socket);
+ });
+ }
+}
+
+void QMinimalHttpServer::onTcpDataReceived(QTcpSocket *socket)
+{
+ QByteArray data = socket->readAll();
+ #ifdef QT_DEBUG
+ qDebug() << "QMinimalHttpServer::onTcpDataReceived " << data;
+ #endif
+ this->processTcpData(data, socket);
+}
+
+void QMinimalHttpServer::processTcpData(const QByteArray &data, QTcpSocket *socket)
+{
+ QStringList lines = QString::fromUtf8(data).split("\r\n");
+ QStringList request = lines[0].split(" ", QString::SkipEmptyParts);
+ QString responseHead = QStringLiteral("HTTP/1.1 200 OK\r\n");
+ QByteArray responseBody;
+ int status = 200;
+
+ QString filename = request[1].toUpper();
+ if (!filename.startsWith("/"))
+ filename = QStringLiteral("/") + filename;
+ filename = filename.replace("%20", " ");
+
+ if (request[0].toUpper() == "GET") {
+ if (httpFiles.contains(filename)) {
+ responseBody = httpFiles[filename];
+ responseHead += QStringLiteral("content-type: ") + httpFileMimeTypes[filename] + "\r\n";
+ } else if (this->processHttpGetRequest(filename, responseHead, responseBody)) {
+ // in this case, everything must be done inside processGetRequest
+ } else {
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ status = 404;
+ }
+
+ } else if (request[0].toUpper() == "POST") {
+
+ // find and validate "Content-Length:" header
+ int contentLength = -1;
+ int i = 0;
+ for (; i < lines.size(); i++) {
+ if (lines[i].startsWith("Content-Length:", Qt::CaseInsensitive))
+ contentLength = lines[i].mid(15).trimmed().toInt();
+ if (lines[i].trimmed()=="")
+ break;
+ }
+ if (contentLength < 0) {
+ responseHead = "HTTP/1.0 411 Length Required\r\n";
+ status = 411;
+ } else if (contentLength > maxPostRequestContentLength) {
+ responseHead = "HTTP/1.0 413 Payload Too Large\r\n";
+ status = 413;
+ }
+
+ // get the requests body
+ int postBodyOffset = -1;
+ for (int i = 0; postBodyOffset < 0 && i < data.size()-4; i++)
+ if (data[i] == '\r' && data[i+1] == '\n' && data[i+2] == '\r' && data[i+3] == '\n')
+ postBodyOffset = i+4;
+ QByteArray postBody;
+ if (0 <= postBodyOffset && postBodyOffset < data.size())
+ postBody = data.mid(postBodyOffset);
+
+ // multi-part message, wait for more packets
+ while (status == 200 && postBody.size() < contentLength) {
+ if (socket->waitForReadyRead(2000)) {
+ QByteArray moreData = socket->readAll();
+ #ifdef QT_DEBUG
+ qDebug() << "QMinimalHttpServer::processTcpData MORE DATA:" << moreData;
+ #endif
+ postBody.append(moreData);
+ } else {
+ responseHead = "HTTP/1.0 408 Request Timeout\r\n";
+ status = 408;
+ }
+ }
+
+ // call the handler
+ if (status == 200)
+ status = this->processHttpPostRequest(filename, postBody, responseHead, responseBody);
+
+ } else if (request[0].toUpper() == "SUBSCRIBE") {
+ this->processHttpSubscribeRequest(filename, lines, responseHead, responseBody);
+ } else if (request[0].toUpper() == "UNSUBSCRIBE") {
+ this->processHttpUnsubscribeRequest(filename, lines, responseHead, responseBody);
+ }
+
+
+ responseHead += QStringLiteral(
+ "content-length: ") + QString::number(responseBody.size()) + "\r\n"
+ "last-modified: Tue, 23 Jan 2018 15:54:00 GMT\r\n"
+ "date: " + DateRfc7231() + "\r\n"
+ "connection: close\r\n";
+
+ #ifdef QT_DEBUG
+ qDebug() << "QMinimalHttpServer::processTcpData" << responseHead << responseBody;
+ #endif
+
+ socket->write((responseHead+"\r\n").toUtf8());
+ socket->write(responseBody);
+}
+
+/***************************************************************************\
+ * Overrides of this method may add headers and set the responseBody. *
+ * returning true means that the request has successfully been processed *
+ * returning false means that the (overridden) method could not deliver *
+ * a response, so then a 404 will be sent. *
+\***************************************************************************/
+bool QMinimalHttpServer::processHttpGetRequest(QString urlUpper, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(urlUpper);
+ Q_UNUSED(responseHead);
+ Q_UNUSED(responseBody);
+ return false;
+}
+
+/***************************************************************************\
+ * Overrides of this method may add headers and set the responseBody. *
+ * return value should be an HTTP status code corresponding to the *
+ * status that is set in the responseHead. *
+ * Since the method is only invoked if the status was 200 before, *
+ * returning 200 is valid in cases where responseHead is not changed *
+\***************************************************************************/
+int QMinimalHttpServer::processHttpPostRequest(QString urlUpper, QByteArray &postBody, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(urlUpper);
+ Q_UNUSED(postBody);
+ Q_UNUSED(responseBody);
+ responseHead = "HTTP/1.0 403 Forbidden\r\n";
+ return 403;
+}
+
+int QMinimalHttpServer::processHttpSubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(urlUpper);
+ Q_UNUSED(requestLines);
+ Q_UNUSED(responseBody);
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+}
+
+int QMinimalHttpServer::processHttpUnsubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(urlUpper);
+ Q_UNUSED(requestLines);
+ Q_UNUSED(responseBody);
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+}
+
+
+
+void QMinimalHttpServer::startListening(quint16 port)
+{
+ if (isListening())
+ return;
+ tcpServer.listen(QHostAddress::Any, port);
+}
+
+void QMinimalHttpServer::stopListening()
+{
+ if (!isListening())
+ return;
+ tcpServer.close();
+}
+
+bool QMinimalHttpServer::isListening()
+{
+ return tcpServer.isListening();
+}
+
+QString QMinimalHttpServer::DateRfc7231(const QDateTime &date)
+{
+ static const QString daysEn[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+ static const QString monthsEn[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ QString sDate = daysEn[ date.date().dayOfWeek() - 1 ]
+ + date.toString(", dd ")
+ + monthsEn[ date.date().month() - 1 ]
+ + date.toString(" yyyy HH:mm::ss")
+ + " GMT";
+ return std::move(sDate);
+}
+QString QMinimalHttpServer::DateRfc7231()
+{
+ return std::move(DateRfc7231(QDateTime::currentDateTimeUtc()));
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.h
new file mode 100644
index 0000000..5b573e9
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qminimalhttpserver.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMINIMALHTTPSERVER_H
+#define QMINIMALHTTPSERVER_H
+
+#include <QObject>
+#include <QMap>
+#include <QDateTime>
+#include <QMimeDatabase>
+#include <QTcpServer>
+#include <QTcpSocket>
+
+class QMinimalHttpServer : public QObject
+{
+ Q_OBJECT
+protected:
+ QTcpServer tcpServer;
+ QMap<QString, QByteArray> httpFiles;
+ QMap<QString, QString> httpFileMimeTypes;
+ int maxPostRequestContentLength = INT_MAX;
+
+ void onNewTcpConnection();
+ void onTcpDataReceived(QTcpSocket *socket);
+ virtual void processTcpData(const QByteArray &data, QTcpSocket *socket);
+ virtual bool processHttpGetRequest(QString urlUpper, QString &responseHead, QByteArray &responseBody);
+ virtual int processHttpPostRequest(QString urlUpper, QByteArray &postBody, QString &responseHead, QByteArray &responseBody);
+ virtual int processHttpSubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody);
+ virtual int processHttpUnsubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody);
+
+ static QString DateRfc7231(const QDateTime &date);
+ static QString DateRfc7231();
+
+public:
+ explicit QMinimalHttpServer(QObject *parent = nullptr);
+ virtual ~QMinimalHttpServer();
+ Q_DISABLE_COPY(QMinimalHttpServer)
+
+ void addFile(QString filename, QByteArray &data, QString mimetype = QString());
+ void startListening(quint16 port = 0);
+ void stopListening();
+ bool isListening();
+};
+
+#endif // QMINIMALHTTPSERVER_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/HomeView.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/HomeView.qml
new file mode 100644
index 0000000..2dd9dd7
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/HomeView.qml
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.3
+import QtStudio3D 1.0
+
+Item {
+ id: home
+
+ property real red: 0
+ property real blue: 255
+ property real green: 0
+ property real light: 0
+
+ property string currentTempAttribute: ""
+ property string currentLightAttribute: ""
+
+ Timer {
+ id: goToHomeTimer
+ interval: 30000
+ running: false
+ repeat: false
+
+ onTriggered: presentation.goToSlide("Scene", "BackToInitialView")
+ }
+
+ Timer {
+ id: showMenuTimer
+ interval: 1000
+ running: false
+ repeat: false
+
+ onTriggered: mainMenu.visible = true
+ }
+
+ signal studio3DPresentationReady()
+
+ function getRoomName(index) {
+ var name;
+ if (index === 0)
+ name = "BackToInitialView"
+ else if (index === 1)
+ name = "Livingroom"
+ else if (index === 2)
+ name = "Masterbedroom"
+ else if (index === 3)
+ name = "Bedroom"
+ else if (index === 4)
+ name = "Bathroom"
+ return name
+ }
+
+ //
+ // Qt 3D Studio presentation
+ //
+ Studio3D {
+ anchors.fill: parent
+
+ ViewerSettings {
+ scaleMode: ViewerSettings.ScaleModeFill
+ }
+
+ Presentation {
+ id: presentation
+ source: "qrc:/uip/houseStudio.uip"
+
+ SceneElement {
+ id: scene
+ elementPath: "Scene"
+ onCurrentSlideNameChanged: {
+ var lightNum = 0
+ var startTimer = false;
+ if (currentSlideName === "Livingroom") {
+ currentTempAttribute = "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_LivingRoom.HeatAreas_Heat_LivingRoom.Heat_LivingRoomSG"
+ currentLightAttribute = "Scene.3D.RoomLights.LivingroomLightMap.House"
+ livingRoomHeat.goToTime(2)
+ masterBedroomHeat.goToTime(0)
+ bedroomHeat.goToTime(0)
+ bathRoomHeat.goToTime(0)
+ entranceHeat.goToTime(0)
+ sliderToolbar.visible = true
+ lightNum = 1
+ } else if (currentSlideName === "Masterbedroom") {
+ currentTempAttribute = "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_MasterBedroom.HeatAreas_Heat_MasterBedroom.Heat_MasterBedroomSG"
+ currentLightAttribute = "Scene.3D.RoomLights.MasterbedroomLightmap.House"
+ livingRoomHeat.goToTime(0)
+ masterBedroomHeat.goToTime(2)
+ bedroomHeat.goToTime(0)
+ bathRoomHeat.goToTime(0)
+ entranceHeat.goToTime(0)
+ sliderToolbar.visible = true
+ lightNum = 2
+ } else if (currentSlideName === "Bedroom") {
+ currentTempAttribute = "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_BedRoom.HeatAreas_Heat_BedRoom.Heat_BedRoomSG"
+ currentLightAttribute = "Scene.3D.RoomLights.BedroomLightmap.House"
+ livingRoomHeat.goToTime(0)
+ masterBedroomHeat.goToTime(0)
+ bedroomHeat.goToTime(2)
+ bathRoomHeat.goToTime(0)
+ entranceHeat.goToTime(0)
+ sliderToolbar.visible = true
+ lightNum = 3
+ } else if (currentSlideName === "Bathroom") {
+ currentTempAttribute = "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_BathRoom.HeatAreas_Heat_BathRoom.Heat_BathRoomSG"
+ currentLightAttribute = "Scene.3D.RoomLights.BathroomLightmap.House"
+ livingRoomHeat.goToTime(0)
+ masterBedroomHeat.goToTime(0)
+ bedroomHeat.goToTime(0)
+ bathRoomHeat.goToTime(2)
+ entranceHeat.goToTime(0)
+ sliderToolbar.visible = true
+ lightNum = 4
+ } else if (currentSlideName === "Entrance") {
+ currentTempAttribute = "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_Entrance.Heat_Entrance_HeatAreas.Heat_EntranceSG"
+ currentLightAttribute = "Scene.3D.RoomLights.EntranceLightmap.House"
+ livingRoomHeat.goToTime(0)
+ masterBedroomHeat.goToTime(0)
+ bedroomHeat.goToTime(0)
+ bathRoomHeat.goToTime(0)
+ entranceHeat.goToTime(2)
+ sliderToolbar.visible = true
+ } else if (currentSlideName === "FloorPlan") {
+ livingRoomHeat.goToTime(0)
+ masterBedroomHeat.goToTime(0)
+ bedroomHeat.goToTime(0)
+ bathRoomHeat.goToTime(0)
+ entranceHeat.goToTime(0)
+ startTimer = true;
+ sliderToolbar.visible = false
+ } else {
+ sliderToolbar.visible = false
+ }
+
+ if (currentSlideName === "FloorPlan") {
+ if (previousSlideName === "InitialView")
+ mainMenu.visible = true
+ else
+ showMenuTimer.start()
+ } else {
+ if (showMenuTimer.running)
+ showMenuTimer.stop()
+ mainMenu.visible = false
+ }
+
+ if (startTimer)
+ goToHomeTimer.start()
+ else if (goToHomeTimer.running)
+ goToHomeTimer.stop()
+
+ presentation.setAttribute(currentTempAttribute, "diffuse.r", red)
+ presentation.setAttribute(currentTempAttribute, "diffuse.g", green)
+ presentation.setAttribute(currentTempAttribute, "diffuse.b", blue)
+ presentation.setAttribute(currentLightAttribute, "opacity", light)
+
+ if (knxBackend) {
+ lightControlLoader.item.lightNum = lightNum
+ lightControlLoader.item.updateLight(knxBackend.getLightState(lightNum))
+ tempSlider.setPositionByColor(knxBackend.getColor())
+ console.log("<<<<<<<<<<<<<<<<<<<1")
+ }
+ }
+ }
+
+ SceneElement {
+ id: livingRoomHeat
+ elementPath: "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_LivingRoom"
+ }
+ SceneElement {
+ id: masterBedroomHeat
+ elementPath: "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_MasterBedroom"
+ }
+ SceneElement {
+ id: bedroomHeat
+ elementPath: "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_BedRoom"
+ }
+ SceneElement {
+ id: bathRoomHeat
+ elementPath: "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_BathRoom"
+ }
+ SceneElement {
+ id: entranceHeat
+ elementPath: "Scene.3D.HeatAreas.Group_HeatAreas.HeatAreas_Heat_Entrance"
+ }
+ }
+
+ // Once https://bugreports.qt.io/browse/QT3DS-414 is solved uncomment the following lines.
+// onPresentationReady: {
+// if (presentationReady)
+// home.studio3DPresentationReady()
+// }
+
+ }
+
+ Connections {
+ target: knxBackend
+ onRoomChanged: presentation.goToSlide("Scene", getRoomName(roomId))
+ onBoardUpdate: {
+ console.log("signal onBoardUpdate lightNum: " + lightNum)
+ if (lightNum > 0
+ && lightNum < 5
+ && lightControlLoader.item.lightNum == lightNum
+ && knxBackend.getLightState(lightNum) != lightControlLoader.item.checked) {
+ var oldValue = houseModel.data(houseModel.index(lightNum - 1, 0), 3)
+ houseModel.setData(houseModel.index(lightNum - 1, 0), !oldValue, 3)
+ lightControlLoader.item.value = houseModel.data(houseModel.index(lightNum - 1, 0), 3)
+ lightControlLoader.item.updateLight(knxBackend.getLightState(lightNum))
+ console.log("lightControlLoader: " + lightControlLoader.item.value)
+ }
+ }
+ onColorLedChange: {
+ var sliderColor = Qt.rgba(tempSlider.redColor, tempSlider.greenColor, tempSlider.blueColor, 1)
+ if (!Qt.colorEqual(sliderColor, color))
+ tempSlider.setPositionByColor(color)
+ }
+// knxBoard.changeColorLeftLed(color)
+// onRockerChange: {
+// logo.rotation = (position - 1000) * 360 / 1000;
+// }
+ }
+
+ MouseArea {
+ id: mouseArea
+ property bool disableMouseEvents: false
+ anchors.fill: parent
+ onClicked: {
+ if (!disableMouseEvents) {
+ if (scene.currentSlideName === "BackToInitialView") {
+ presentation.goToSlide("Scene", "InitialView")
+ disableMouse(2200)
+ } else if (scene.currentSlideName === "FloorPlan") {
+ presentation.goToSlide("Scene", "BackToInitialView")
+ disableMouse(2100)
+ } else if (scene.currentSlideName !== "InitialView") {
+ presentation.goToSlide("Scene", "FloorPlan")
+ disableMouse(1000)
+ }
+ }
+ }
+
+ function disableMouse(animationDuration) {
+ disableMouseEvents = true
+ mouseTimer.interval = animationDuration
+ mouseTimer.start()
+ }
+
+ Timer {
+ id: mouseTimer
+ interval: 1000
+ running: false
+ repeat: false
+
+ onTriggered: mouseArea.disableMouseEvents = false
+ }
+ }
+
+ //
+ // Room label items
+ //
+ MainMenu {
+ id: mainMenu
+
+ property int currentIndex: -1
+
+ visible: false
+ anchors.fill: parent
+
+ onCurrentMenuItemChanged: {
+ presentation.goToSlide("Scene", currentItem)
+
+ // Store temperature and light to model before changing the slider value
+ if (currentIndex != -1) {
+ houseModel.setData(houseModel.index(currentIndex, 0), tempSlider.currentValue, 2)
+ houseModel.setData(houseModel.index(currentIndex, 0), lightControlLoader.item.currentValue, 3)
+ }
+ currentIndex = index
+ var temp = houseModel.data(houseModel.index(index, 0), 2)
+ tempSlider.value = (temp - 15) / 15
+ lightControlLoader.item.value = houseModel.data(houseModel.index(index, 0), 3)
+ }
+ }
+
+ //
+ // Toolbar for Sliders
+ //
+ Item {
+ id: sliderToolbar
+ anchors.bottom: parent.bottom
+ height: tempSlider.height
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: lightControlLoader.width + sizesMap.controlMargin + tempSlider.width
+
+ visible: false
+
+ Loader {
+ id: lightControlLoader
+ source: knxBackend ? "LightSwitch.qml" : "LightSlider.qml"
+ asynchronous: true
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: sizesMap.controlMargin
+ anchors.left: parent.left
+ width: knxBackend ? (sizesMap.controlHeight * 2) : (mainMenu.width / 3)
+ }
+
+ Connections {
+ target: lightControlLoader.item
+ onLightValueChanged: {
+ var newLightValue = lightControlLoader.item.lightValue * 100
+ home.light = newLightValue
+ presentation.setAttribute(currentLightAttribute, "opacity", newLightValue)
+
+ }
+ }
+
+ TempSlider {
+ id: tempSlider
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: sizesMap.controlMargin
+ anchors.right: parent.right
+ width: mainMenu.width / 3
+
+ onRedColorChanged: {
+ home.red = redColor
+ presentation.setAttribute(currentTempAttribute, "diffuse.r", redColor)
+ }
+ onBlueColorChanged: {
+ home.blue = blueColor
+ presentation.setAttribute(currentTempAttribute, "diffuse.b", blueColor)
+ }
+
+ onGreenColorChanged: {
+ home.green = greenColor
+ presentation.setAttribute(currentTempAttribute, "diffuse.g", greenColor)
+ }
+
+ onEconomyChanged: {
+ if (knxBackend) {
+ // Toggle red light based on temperature changes
+ // The initial state of red lights on the board needs to be based on the default temperatures
+ var lightNum = 0
+ if (scene.currentSlideName === "Livingroom")
+ lightNum = 9
+ else if (scene.currentSlideName === "Masterbedroom")
+ lightNum = 10
+ else if (scene.currentSlideName === "Bedroom")
+ lightNum = 11
+ else if (scene.currentSlideName === "Bathroom")
+ lightNum = 12
+ //knxBackend.toggleLight(lightNum)
+ }
+ }
+ }
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSlider.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSlider.qml
new file mode 100644
index 0000000..8f00abd
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSlider.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+
+SliderControl {
+ id: lightSlider
+
+ property real lightValue: lightSlider.position
+
+ sliderColor: "black"
+ currentValue: lightValue.toFixed(1)
+
+ text: currentValue * 100 + "%"
+ iconSource: "qml/images/icon_light.png"
+
+ onPositionChanged: {
+ setNewLightColor()
+ }
+
+ function setNewLightColor() {
+ // From black to white
+ var newColorValue = lightSlider.position * 255
+ sliderColor = rgbToHex(newColorValue, newColorValue, newColorValue)
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSwitch.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSwitch.qml
new file mode 100644
index 0000000..86fe602
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/LightSwitch.qml
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.3
+import Style 1.0
+
+Item {
+ id: lightSwitch
+ property real value: control.checked ? 1.0 : 0.0
+ property real lightValue: control.position
+ property real currentValue: lightValue.toFixed(1)
+ property real lightNum: 0
+
+ width: sizesMap.controlHeight * 2
+ height: sizesMap.controlHeight + sliderText.height
+ function updateLight(state) {
+ control.checked = state
+ }
+
+ Text {
+ id: sliderText
+ anchors.bottom: control.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: sizesMap.fontSize
+ color: Style.textColor
+ font.bold: true
+ style: Text.Outline
+ styleColor: Style.sliderBackgroundColor
+ }
+
+ Switch {
+ id: control
+ width: lightSwitch.width
+ height: sizesMap.controlHeight
+
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: sizesMap.controlMargin / 2
+ onClicked: {
+ console.log('Clicked on ligth!'+ lightNum)
+ knxBackend.toggleLight(lightNum)
+ }
+ indicator: Rectangle {
+ implicitWidth: sizesMap.controlHeight * 2
+ implicitHeight: sizesMap.controlHeight
+ x: control.leftPadding
+ y: control.topPadding + control.availableHeight / 2 - height / 2
+ radius: height / 2
+ color: control.checked ? Style.sliderSelectionColor : Style.sliderBackgroundColor
+ border.color: Style.backgroundColor
+ border.width: sizesMap.controlBorderWidth
+ opacity: control.enabled ? 1 : 0.3
+
+ Rectangle {
+ x: control.checked ? parent.width - width : 0
+ width: sizesMap.controlHeight
+ height: sizesMap.controlHeight
+ radius: height / 2
+ antialiasing: true
+ color: Style.backgroundColor
+ opacity: control.enabled ? 1 : 0.3
+ Image {
+ id: handleItemIcon
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ anchors.margins: sizesMap.controlMargin / 2
+ anchors.centerIn: parent
+ source: "qml/images/icon_light.png"
+ }
+ }
+ }
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/MainMenu.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/MainMenu.qml
new file mode 100644
index 0000000..dcbb281
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/MainMenu.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import Style 1.0
+
+Item {
+ id: menuItem
+ property int horizontalScreenCenter: main.width / 2
+ property int verticalScreenCenter: main.height / 2
+
+ signal currentMenuItemChanged(int index, string currentItem)
+
+ Repeater {
+ id: mainListView
+ model: houseModel
+ delegate: listElement
+ }
+
+ // Delegate for items in list view
+ Component {
+ id: listElement
+
+ RoomLabel {
+ // Position is defined in the model relative to the center of the screen.
+ // Scale the label position here.
+ x: menuItem.horizontalScreenCenter + (heightRatio * xPos) - sizesMap.labelMouseMargin
+ y: menuItem.verticalScreenCenter + (heightRatio * yPos) - sizesMap.labelMouseMargin
+ text: name
+ onRoomLabelClicked: currentMenuItemChanged(index, item)
+ }
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/RoomLabel.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/RoomLabel.qml
new file mode 100644
index 0000000..f948917
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/RoomLabel.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import Style 1.0
+
+Item {
+ id: roomLabel
+
+ // Provide bigger mouse area for label than the visual label is
+
+ property alias text: roomText.text
+
+ signal roomLabelClicked
+
+ height: sizesMap.controlHeight
+ width: labelRect.width + sizesMap.labelMouseMargin * 2
+
+ Rectangle {
+ id: labelRect
+ width: roomText.width + sizesMap.controlMargin * 2
+ height: roomText.height + sizesMap.controlMargin
+ anchors.centerIn: parent
+ color: Style.sliderBackgroundColor
+ radius: width / 2
+ border.color: Style.backgroundColor
+ border.width: sizesMap.controlBorderWidth
+
+ Text {
+ id: roomText
+ anchors.centerIn: parent
+ font.pixelSize: sizesMap.fontSize
+ color: Style.textColor
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: roomLabelClicked()
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SliderControl.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SliderControl.qml
new file mode 100644
index 0000000..14c6f5d
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SliderControl.qml
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import Style 1.0
+
+Item {
+ id: sliderControl
+ signal moved(real position)
+
+ property alias position: control.position
+ property alias value: control.value
+ property alias text: sliderText.text
+ property alias iconSource: handleItemIcon.source
+
+ property color sliderColor
+ property real currentValue: 0
+
+ width: sizesMap.sliderMaxWidth
+ height: sizesMap.controlHeight + sliderText.height
+
+ Text {
+ id: sliderText
+ anchors.bottom: control.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: sizesMap.fontSize
+ color: Style.textColor
+ font.bold: true
+ style: Text.Outline
+ styleColor: Style.sliderBackgroundColor
+ }
+
+ Slider {
+ id: control
+
+ width: sliderControl.width
+ height: sizesMap.controlHeight
+
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: sizesMap.controlMargin / 2
+
+ onMoved: parent.moved(position)
+
+ background: Rectangle {
+ x: control.leftPadding
+ y: control.topPadding + control.availableHeight / 2 - height / 2
+ implicitWidth: sizesMap.sliderMaxWidth
+ implicitHeight: sizesMap.controlHeight
+ width: control.availableWidth
+ height: implicitHeight
+ color: Style.sliderBackgroundColor
+ radius: height / 2
+ border.color: Style.backgroundColor
+ border.width: sizesMap.controlBorderWidth
+ opacity: control.enabled ? 1 : 0.3
+
+ Rectangle {
+ width: handleItem.x + handleItem.width - 5
+ height: parent.height
+ color: Style.sliderSelectionColor
+ border.color: Style.backgroundColor
+ border.width: sizesMap.controlBorderWidth
+ radius: height / 2
+ }
+ }
+
+ handle: Rectangle {
+ id: handleItem
+ x: control.leftPadding + control.visualPosition * (control.availableWidth - width)
+ y: control.topPadding + control.availableHeight / 2 - height / 2
+ implicitWidth: sizesMap.controlHeight
+ implicitHeight: sizesMap.controlHeight
+ radius: height / 2
+ antialiasing: true
+ color: Style.backgroundColor
+ opacity: control.enabled ? 1 : 0.3
+ Image {
+ id: handleItemIcon
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ anchors.margins: sizesMap.controlMargin / 2
+ anchors.centerIn: parent
+
+ }
+ }
+ }
+
+ function rgbToHex(red, green, blue) {
+ // Based on http://www.javascripter.net/faq/rgbtohex.htm
+ return "#" + toHex(red) + toHex(green) + toHex(blue)
+ }
+
+ function toHex(n) {
+ if (isNaN(n))
+ return "00"
+ n = Math.max(0, Math.min(n, 255))
+ return "0123456789ABCDEF".charAt((n - n % 16) / 16)
+ + "0123456789ABCDEF".charAt(n % 16)
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SplashScreen.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SplashScreen.qml
new file mode 100644
index 0000000..94df270
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/SplashScreen.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import Style 1.0
+
+Rectangle {
+ anchors.fill: parent
+ color: Style.backgroundColor
+
+ Image {
+ anchors.centerIn: parent
+ source: "qrc:/qml/images/QtSymbol.png"
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/TempSlider.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/TempSlider.qml
new file mode 100644
index 0000000..8220669
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/TempSlider.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+
+SliderControl {
+ id: tempSlider
+ property real redColor
+ property real blueColor
+ property real greenColor
+ property bool economy: currentValue < 22 ? true : false
+
+ currentValue: 15
+ sliderColor: "#0000ff"
+
+ text: currentValue + "°"
+ iconSource: "qml/images/icon_temp.png"
+
+ onPositionChanged: {
+ updateCurrentTemp()
+ setNewTempColor()
+ }
+
+ onMoved: {
+ var position = 0.6;
+ if (currentValue > 17 && currentValue < 26)
+ position = 0.45;
+ else if (currentValue >= 26)
+ position = 0.30;
+ knxBackend.colorSwitch(position)
+ console.log('moved color slider!'+ position)
+ }
+
+ function setPositionByColor(color)
+ {
+ if (Qt.colorEqual(color, "magenta")) {
+ value = 0.5
+ }
+ else if (Qt.colorEqual(color, "red")) {
+ value = 1
+ }
+ else if (Qt.colorEqual(color, "blue")) {
+ value = 0
+ }
+ }
+
+ function updateCurrentTemp() {
+ // Temperature range from 15 to 30
+ // Slider range form 0 to 1
+ var newTempValue = 15 + 15 * tempSlider.position
+ tempSlider.currentValue = newTempValue.toFixed(0)
+ }
+
+ function setNewTempColor() {
+ var position = tempSlider.position * 100
+ // From blue to red
+ var r = Math.floor((255 * Math.sqrt(Math.sin(position * Math.PI / 200))))
+ var b = Math.floor((255 * Math.sqrt(Math.cos(position * Math.PI / 200))))
+ var g = 0
+ redColor = r / 255
+ blueColor = b / 255
+ greenColor = 0
+ sliderColor = rgbToHex(r, g, b)
+
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/main.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/main.qml
new file mode 100644
index 0000000..ca42332
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/HomeAutom/main.qml
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import Style 1.0
+
+// Main Item
+Item {
+ id: main
+ width: sizesMap.screenWidth
+ height: sizesMap.screenHeight
+
+ // onPresentationReady() signal should be restored to 3D studio code so that we can hide
+ // the splashscreen without a timer, https://bugreports.qt.io/browse/QT3DS-414
+ Timer {
+ id: showSplashScreenTimer
+ interval: 1000
+ running: false
+ repeat: false
+
+ onTriggered: hideSplashScreen()
+ }
+
+ Loader {
+ id: appLoader
+ anchors.fill: parent
+ visible: false
+// asynchronous: true // https://bugreports.qt.io/browse/QTBUG-50992
+ }
+
+ Connections {
+ target: appLoader.item
+ onStudio3DPresentationReady: hideSplashScreen()
+ }
+
+ Timer {
+ interval: 5000
+ running: true
+ repeat: true
+ onTriggered: knxBackend.reconnect()
+ }
+
+ SplashScreen {
+ id: splashScreenLoader
+ visible: true
+ anchors.fill: parent
+ Component.onCompleted: {
+ appLoader.setSource("HomeView.qml")
+ showSplashScreenTimer.start()
+ }
+ }
+
+ function hideSplashScreen() {
+ if (appLoader.status === Loader.Ready) {
+ splashScreenLoader.visible = false
+ appLoader.visible = true
+ }
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/QtSymbol.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/QtSymbol.png
new file mode 100644
index 0000000..3c867cd
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/QtSymbol.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fc885612c701d0b610bebe156dcb4b9d819a1ad6681465a53392705fed2b9d90
+size 4541
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_light.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_light.png
new file mode 100644
index 0000000..2b35771
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:00eec2e449fdc77fb81df23a8959bb83804ebd366f313014a36eb0bb81e5a740
+size 1210
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_temp.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_temp.png
new file mode 100644
index 0000000..a82320b
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/images/icon_temp.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:32584803b4e6fdfb4000954d88056b81f25ae849afdc64f112124ddd95243252
+size 1207
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/Style.qml b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/Style.qml
new file mode 100644
index 0000000..451d231
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/Style.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+
+import QtQuick 2.8
+
+QtObject {
+
+ // Theme colors to be used through out whole system
+ readonly property color backgroundColor: "white"
+ readonly property color textColor: "white"
+ readonly property color sliderToolbarTextColor: "white"
+ readonly property color sliderToolbarRaisedTextColor: "black"
+ readonly property color menuBackgroundColor: "gray"
+ readonly property color menuSelectedItemColor: "#80bfff"
+ readonly property color sliderBackgroundColor: "#595959"
+ readonly property color sliderSelectionColor: "#a6a6a6"
+
+ readonly property int visibilityAnimatorDuration: 500
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/qmldir b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/qmldir
new file mode 100644
index 0000000..858dcaf
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qml/imports/Style/qmldir
@@ -0,0 +1,2 @@
+module Style
+singleton Style 1.0 Style.qml
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp
new file mode 100644
index 0000000..b6e3d50
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "demodatapoint.h"
+#include "qmlknxdemo.h"
+#include "utils.h"
+
+#include <QtCore/QString>
+#include <QtGui/QColor>
+#include <QtKnx/QKnxAddress>
+#include <QtNetwork/QNetworkAddressEntry>
+#include <QtNetwork/QNetworkInterface>
+
+namespace {
+ const double sliderSectionSize = 1 / 7.0;
+ using DeviceNumbers = EtsDevelopmentBoard::DeviceNumbers;
+}
+
+QmlKnxDemo::QmlKnxDemo()
+ : m_tunnel(this)
+{
+ checkLightStatusOn();
+
+ if (auto blind = m_etsBoard.getBlind()) {
+ connect(blind, &DemoBlindDataPoint::blindChange, this, &QmlKnxDemo::blindPositionChange);
+ connect(blind, &DemoBlindDataPoint::blindFullyUp, this, &QmlKnxDemo::blindFullyUp);
+ connect(blind, &DemoBlindDataPoint::blindFullyDown, this, &QmlKnxDemo::blindFullyDown);
+ }
+
+ if (auto rocker = m_etsBoard.getRocker())
+ connect(rocker, &DemoRockerDataPoint::rockerChange, this, &QmlKnxDemo::rockerChange);
+
+ if (auto colorLed = m_etsBoard.getColorLed())
+ connect(colorLed, &DemoColorLed::colorChange, this, &QmlKnxDemo::colorLedChange);
+}
+
+void QmlKnxDemo::toggleLight(int light)
+{
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(light))) {
+ dpt->uiToggle();
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(light), dpt->bytes());
+ }
+}
+
+void QmlKnxDemo::colorSwitch(double value)
+{
+ QColor colorAtStart = colorState;
+ if (value < (sliderSectionSize / 2)
+ && colorState != Qt::black)
+ colorState = Qt::black;
+
+ else if ((value > (sliderSectionSize / 2))
+ && value < (3 * sliderSectionSize / 2)
+ && (colorState != Qt::white))
+ colorState = Qt::white;
+
+ else if ((value > (3 * sliderSectionSize / 2))
+ && value < (5 * sliderSectionSize / 2)
+ && (colorState != Qt::red))
+ colorState = Qt::red;
+
+ else if ((value > (5 * sliderSectionSize / 2))
+ && value < (7 * sliderSectionSize / 2)
+ && (colorState != Qt::magenta))
+ colorState = Qt::magenta;
+
+ else if ((value > (7 * sliderSectionSize / 2))
+ && value < (9 * sliderSectionSize / 2)
+ && (colorState != Qt::blue))
+ colorState = Qt::blue;
+
+ else if ((value > (9 * sliderSectionSize / 2))
+ && value < (11 * sliderSectionSize / 2)
+ && (colorState != Qt::cyan))
+ colorState = Qt::cyan;
+
+ else if (value > (11 * sliderSectionSize / 2)
+ && value < (13 * sliderSectionSize / 2)
+ && (colorState != Qt::green))
+ colorState = Qt::green;
+
+ else if (value > ((6 * sliderSectionSize) + (sliderSectionSize / 2))
+ && (colorState != Qt::yellow))
+ colorState = Qt::yellow;
+
+ if (colorAtStart != colorState) {
+ if (auto led = m_etsBoard.getColorLed()) {
+ led->setCurrentColor(colorState);
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ }
+ }
+}
+
+void QmlKnxDemo::toggleMiddleRight()
+{
+ auto light = DeviceNumbers::MIDDLE_RIGHT;
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(light))) {
+ dpt->uiToggle();
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(light), dpt->bytes());
+ }
+}
+
+void QmlKnxDemo::toggleMiddleLeft()
+{
+ auto led = m_etsBoard.getColorLed();
+ if (!led)
+ return;
+
+ if (!led->isOn()) {
+ // set green color in dpt by default...
+ led->setCurrentColor(QColor(0, 255, 0));
+ // send request to ets board
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ } else {
+ led->setCurrentColor(QColor(0, 0, 0));
+ sendColorLedGroupValueWriteFrames(m_tunnel, led);
+ }
+}
+
+QString QmlKnxDemo::getColor() const
+{
+ if (auto obj = m_etsBoard.getColorLed())
+ return obj->currentColor().name();
+ return {};
+}
+
+int QmlKnxDemo::getRockerPosition() const
+{
+ if (auto rocker = m_etsBoard.getRocker())
+ return rocker->position();
+ return 0;
+}
+
+bool QmlKnxDemo::getLightState(int lightNum) const
+{
+ if (auto dpt = static_cast<DemoSwitchDataPoint *>(m_etsBoard.getGroupObject(lightNum)))
+ return dpt->isOn();
+ return false;
+}
+
+int QmlKnxDemo::getBlindPosition() const
+{
+ if (auto blind = m_etsBoard.getBlind())
+ return blind->position();
+ return 0;
+}
+
+void QmlKnxDemo::moveBlindUp()
+{
+ if (auto dpt = m_etsBoard.getBlind()) {
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(DeviceNumbers::E7), dpt->moveUpBytes(),
+ 0xac);
+ }
+}
+
+void QmlKnxDemo::moveBlindDown()
+{
+ if (auto dpt = m_etsBoard.getBlind()) {
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(DeviceNumbers::E7), dpt->moveDownBytes(),
+ 0xac);
+ }
+}
+
+void QmlKnxDemo::stopBlind()
+{
+ auto index = DeviceNumbers::E16;
+ if (auto dpt = static_cast<DemoBlindDataPoint *>(m_etsBoard.getGroupObject(index)))
+ sendGroupValueWrite(m_tunnel, m_etsBoard.getAddress(index), dpt->stopBytes(), 0xac);
+}
+
+void QmlKnxDemo::handleFrame(const QKnxTunnelFrame &frame)
+{
+ auto str = frame.serviceInformation().bytes().toHex();
+ auto dstAdd = frame.destinationAddress().toString();
+
+ if (QKnxCemiFrame::MessageCode::DataConfirmation == frame.messageCode()
+ || QKnxCemiFrame::MessageCode::DataIndication == frame.messageCode()) {
+ // data indication come from pushing buttons on the Board
+ // data confirmation are responses to App UI requests
+ bool boardStateChanged = false;
+ const QKnxAddress dstAddress = frame.destinationAddress();
+ if (m_etsBoard.exists(dstAddress))
+ boardStateChanged = m_etsBoard.getGroupObject(dstAddress)->updateDataPointState(frame);
+
+ if (boardStateChanged)
+ emit boardUpdate(m_etsBoard.getIndex(dstAddress));
+ }
+}
+
+static QHostAddress obtainLocalAddress()
+{
+ auto addresses = QNetworkInterface::allAddresses();
+ for (auto address : qAsConst(addresses)) {
+ if (address.isLoopback() || address.protocol() != QAbstractSocket::IPv4Protocol)
+ continue;
+ qDebug() << "using IP " << address;
+ return address;
+ }
+ qDebug() << "using loopback IP!!!";
+ return QHostAddress::LocalHost; // no local address found!
+}
+
+QmlKnxTunnel::QmlKnxTunnel(QmlKnxDemo *demo)
+{
+ connect(&m_connection, &QKnxNetIpTunnelConnection::stateChanged,
+ this, &QmlKnxTunnel::handleConnection);
+ connect(&m_connection, &QKnxNetIpTunnelConnection::receivedTunnelFrame,
+ demo, &QmlKnxDemo::handleFrame);
+ connect(&m_timer, &QTimer::timeout, this, &QmlKnxTunnel::send);
+ auto newAddress = obtainLocalAddress();
+ m_connection.setLocalAddress(newAddress);
+ m_discoveryAgent.setLocalAddress(newAddress);
+ m_ip.setAddress("192.168.1.50");
+ m_port = 3671;
+ reconnect();
+ qDebug() << " m_ip" << m_ip;
+ // Automatic KNXnet/Ip router discovery. Connects to first router found
+ static auto handleDiscoveredServer = [&](const QKnxNetIpServerInfo &info) {
+ if (!m_connected) {
+ m_ip = info.controlEndpointAddress();
+ m_port = info.controlEndpointPort();
+ // establish the knx tunnel
+ reconnect();
+ m_connected = true;
+ }
+ };
+ connect(&m_discoveryAgent, &QKnxNetIpServerDiscoveryAgent::deviceDiscovered, this,
+ handleDiscoveredServer);
+ autoDiscoverKnxServers();
+}
+
+void QmlKnxTunnel::sendTunnelFrame(const QKnxCemiFrame &frame)
+{
+ if (frame.size() == 0)
+ return;
+
+ if (m_frames.size() == 0)
+ m_timer.start(200);
+ m_frames.enqueue(frame);
+}
+
+void QmlKnxTunnel::reconnect()
+{
+ m_connection.connectToHost(m_ip, m_port);
+}
+
+void QmlKnxTunnel::autoDiscoverKnxServers()
+{
+ if (m_connection.state() != m_connection.Connected) {
+ m_discoveryAgent.stop();
+ m_connected = false;
+ m_discoveryAgent.start();
+ }
+}
+
+void QmlKnxTunnel::changeIp(const QString &ip, quint16 port)
+{
+ m_ip = ip;
+ m_port = port;
+ m_connection.disconnectFromHost();
+}
+
+void QmlKnxTunnel::send()
+{
+ m_connection.sendTunnelFrame(m_frames.dequeue());
+ if (m_frames.size() == 0)
+ m_timer.stop();
+}
+
+void QmlKnxTunnel::handleConnection(QKnxNetIpEndpointConnection::State state)
+{
+ switch (state) {
+ case QKnxNetIpEndpointConnection::State::Disconnected:
+ autoDiscoverKnxServers();
+ break;
+ default:
+ break;
+ }
+}
+
+void QmlKnxDemo::changeTunnelIp(const QString &ipStr, quint16 port)
+{
+ m_tunnel.changeIp(ipStr, port);
+}
+
+void QmlKnxDemo::changeRoom(int roomId)
+{
+ currentRoom = roomId;
+ emit roomChanged(currentRoom);
+}
+
+void QmlKnxDemo::checkLightStatusOn()
+{
+ initBoard(m_etsBoard, m_tunnel);
+}
+
+void QmlKnxDemo::test()
+{
+ static int c = 0;
+ if (c == 0)
+ emit colorLedChange(QColor("blue"));
+ else if (c==1)
+ emit colorLedChange(QColor("magenta"));
+ else if (c==2) {
+ emit colorLedChange(QColor("green"));
+ c = 0;
+ return;
+ }
+ c++;
+}
+
+void QmlKnxDemo::reconnect()
+{
+ m_tunnel.reconnect();
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.h
new file mode 100644
index 0000000..d4dc45c
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qmlknxdemo.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLKNXDEMO_H
+#define QMLKNXDEMO_H
+
+#include "etsdevelopmentboard.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QTimer>
+#include <QtGui/QColor>
+#include <QtKnx/QKnxNetIpServerDiscoveryAgent>
+#include <QtKnx/QKnxNetIpTunnelConnection>
+#include <QtKnx/QKnxTunnelFrame>
+
+class QmlKnxDemo;
+class QmlKnxTunnel : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QmlKnxTunnel)
+
+public:
+ QmlKnxTunnel(QmlKnxDemo *demo);
+ void sendTunnelFrame(const QKnxCemiFrame &frame);
+ void changeIp(const QString &ip, quint16 port = 3671);
+ void autoDiscoverKnxServers();
+ void reconnect();
+public slots:
+ void handleConnection(QKnxNetIpEndpointConnection::State state);
+ void send();
+
+private:
+
+
+ QQueue<QKnxCemiFrame> m_frames;
+ QKnxNetIpTunnelConnection m_connection;
+ QKnxNetIpServerDiscoveryAgent m_discoveryAgent;
+
+ QTimer m_timer;
+ QHostAddress m_ip;
+ quint16 m_port { 3671 };
+ bool m_connected { false };
+};
+
+class QmlKnxDemo : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QmlKnxDemo)
+
+public:
+ QmlKnxDemo();
+
+ Q_INVOKABLE void toggleMiddleRight();
+ Q_INVOKABLE void toggleMiddleLeft();
+ Q_INVOKABLE QString getColor() const;
+ Q_INVOKABLE int getRockerPosition() const;
+ Q_INVOKABLE int getBlindPosition() const;
+ Q_INVOKABLE bool getLightState(int lightNum) const;
+
+ Q_INVOKABLE void moveBlindUp();
+ Q_INVOKABLE void moveBlindDown();
+ Q_INVOKABLE void stopBlind();
+
+ Q_INVOKABLE void colorSwitch(double value);
+ Q_INVOKABLE void toggleLight(int light);
+
+ Q_INVOKABLE void test();
+ Q_INVOKABLE void reconnect();
+ Q_INVOKABLE void changeTunnelIp(const QString &ipStr, quint16 port = 3671);
+
+ Q_INVOKABLE void changeRoom(int roomId);
+
+Q_SIGNALS:
+ void boardUpdate(quint32 lightNum);
+ void blindPositionChange(int position);
+ void blindFullyDown();
+ void blindFullyUp();
+ void rockerChange(int position);
+ void colorLedChange(QColor color);
+ void roomChanged(int roomId);
+
+public slots:
+ void handleFrame(const QKnxTunnelFrame &frame);
+
+private:
+ void checkLightStatusOn();
+
+private:
+ QColor colorState;
+ QmlKnxTunnel m_tunnel;
+ EtsDevelopmentBoard m_etsBoard;
+ int currentRoom = { 0 };
+};
+
+#endif
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.cpp
new file mode 100644
index 0000000..933fe40
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.cpp
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qupnprootdevice.h"
+#include <QCryptographicHash>
+#include <QNetworkDatagram>
+
+// 239.255.255.250:1900 is the IANA reserved UPnP multicast address.
+const QHostAddress QUPnPRootDevice::multicastAddress("239.255.255.250");
+const quint16 QUPnPRootDevice::multicastPort = 1900;
+
+QList<QUPnPRootDevice*> QUPnPRootDevice::allUPnPRootDevices;
+
+QUPnPRootDevice::QUPnPRootDevice(QObject *parent, const QString &name, const QString &searchTarget)
+ : QMinimalHttpServer(parent)
+{
+ allUPnPRootDevices.push_back(this);
+
+ static bool didRandomize = false;
+ if (!didRandomize)
+ qsrand(QTime::currentTime().msec());
+ didRandomize = true;
+
+ foreach (const QHostAddress &address, QNetworkInterface::allAddresses())
+ if (address.protocol() == QAbstractSocket::IPv4Protocol
+ && address != QHostAddress(QHostAddress::LocalHost))
+ this->localIpAddress = address.toString();
+
+ this->searchTarget = searchTarget;
+ this->product = name;
+ this->uuid = createUuid(name);
+ connect(&udpSocket, &QUdpSocket::readyRead, this, &QUPnPRootDevice::onUdpDataReceived);
+}
+
+QUPnPRootDevice::~QUPnPRootDevice()
+{
+ stopListening();
+ allUPnPRootDevices.removeAll(this);
+}
+
+void QUPnPRootDevice::stopAllUPnPRootDevices()
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::stopAllUPnPRootDevices";
+ #endif
+ for (QUPnPRootDevice* dev : allUPnPRootDevices)
+ dev->stopListening();
+}
+
+QString QUPnPRootDevice::getUPnPxml()
+{
+ /*
+ <deviceType>urn:schemas-upnp-org:device:DimmableLight:1</deviceType>
+ <modelDescription>UPnP-to-KNX Bridge</modelDescription>
+ <modelName>UPnP-to-KNX Bridge</modelName>
+ <modelNumber>0.1</modelNumber>
+ <modelURL>https://qt.io</modelURL>
+ <serialNumber>0.1</serialNumber>
+ <presentationURL/>
+ */
+
+ QString upnp_xml = QStringLiteral(
+ "<?xml version=\"1.0\"?>"
+ "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
+ "<specVersion>"
+ "<major>1</major>"
+ "<minor>0</minor>"
+ "</specVersion>"
+ "<device>"
+ "<deviceType>upnp:rootdevice</deviceType>"
+ "<friendlyName>") + this->product + "</friendlyName>"
+ "<manufacturer>" + this->manufacturer + "</manufacturer>"
+ "<manufacturerURL>" + this->manufacturerURL + "</manufacturerURL>"
+ "<modelName>" + this->product + "</modelName>"
+ "<modelNumber>0.1</modelNumber>"
+ "<UDN>uuid:" + this->uuid + "</UDN>";
+
+ // icons
+ if (icons.size() > 0) {
+ upnp_xml += "<iconList>";
+ for (QString iconKey : icons.keys()) {
+ QImage icon = icons[iconKey];
+ upnp_xml += QStringLiteral(
+ "<icon>") +
+ "<mimetype>" + httpFileMimeTypes[iconKey] + "</mimetype>"
+ "<width>" + QString::number(icon.width()) + "</width>"
+ "<height>" + QString::number(icon.height()) + "</height>"
+ "<depth>" + QString::number(icon.depth()) + "</depth>"
+ "<url>" + iconKey + "</url>"
+ "</icon>";
+ }
+ upnp_xml += "</iconList>";
+ }
+
+ // services
+ if (services.size() > 0) {
+ upnp_xml += "<serviceList>";
+ for (auto service : services)
+ upnp_xml += service->upnpServiceListEntry();
+ upnp_xml += "</serviceList>";
+ }
+
+ upnp_xml +=
+ "</device>"
+ "</root>";
+
+ return upnp_xml;
+}
+
+QUPnPService *QUPnPRootDevice::getService(const QString &urlUpper)
+{
+ QString serviceKey;
+ if (urlUpper.startsWith("/") && urlUpper.endsWith("/CONTROL"))
+ serviceKey = urlUpper.mid(1, urlUpper.size() - 9);
+ else if (urlUpper.startsWith("/") && urlUpper.endsWith("/EVENTS"))
+ serviceKey = urlUpper.mid(1, urlUpper.size() - 8);
+ else if (urlUpper.startsWith("/") && urlUpper.endsWith("/SCPD.XML"))
+ serviceKey = urlUpper.mid(1, urlUpper.size() - 10);
+
+ if (serviceKey != "" && services.contains(serviceKey))
+ return services[serviceKey];
+ return nullptr;
+}
+
+void QUPnPRootDevice::onUdpDataReceived()
+{
+ QHostAddress senderAddress;
+ quint16 senderPort;
+ while (udpSocket.hasPendingDatagrams()) {
+ //udpSocket.readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort);
+ QNetworkDatagram datagram = udpSocket.receiveDatagram(int(udpSocket.pendingDatagramSize()));
+ senderAddress = datagram.senderAddress();
+ senderPort = datagram.senderPort();
+#ifdef QT_DEBUG
+ QString sdatagram = QString::fromUtf8(datagram.data());
+ if (!sdatagram.contains("ST: urn:dial-multiscreen-org:")
+ && !sdatagram.contains("ST:urn:schemas-upnp-org:device:InternetGatewayDevice:")
+ && !sdatagram.contains("ST: urn:schemas-upnp-org:device:InternetGatewayDevice:")
+ && !sdatagram.contains("ST:urn:schemas-upnp-org:device:MediaRenderer:")
+ && !sdatagram.contains("ST:urn:schemas-upnp-org:device:MediaServer:")
+ && !sdatagram.contains("NOTIFY * HTTP/")
+ //&& !sdatagram.contains("")
+ ) {
+ qDebug() << "QUPnPRootDevice::onUdpDataReceived " << sdatagram;
+ qDebug() << "QUPnPRootDevice::onUdpDataReceived ip and port:" << senderAddress << senderPort;
+ }
+ #endif
+ processUdpData(QString::fromUtf8(datagram.data()), senderAddress, senderPort);
+ }
+}
+
+void QUPnPRootDevice::processUdpData(const QString &data, QHostAddress senderAddress, quint16 senderPort)
+{
+ if (!data.startsWith("M-SEARCH")
+ || !data.contains("MAN: \"ssdp:discover\"", Qt::CaseInsensitive)
+ || ( !data.contains("ST: ssdp:all", Qt::CaseInsensitive)
+ && !data.contains("ST: upnp:rootdevice", Qt::CaseInsensitive)
+ && !data.contains(QStringLiteral("ST: ") + this->searchTarget, Qt::CaseInsensitive)))
+ return;
+
+ // SSDP Requests should not be answered immediately, because the sender of the
+ // request might get many results and might run on weak hardware.
+ int responseDelay = 1000; // milliseconds
+ QStringList lines = data.split("\r\n");
+ for (QString line : lines) {
+ if (line.startsWith("MX:", Qt::CaseInsensitive))
+ responseDelay = 1000 * line.mid(3).trimmed().toInt();
+ }
+ if (responseDelay > 0)
+ responseDelay = qrand() % responseDelay;
+
+ QTimer::singleShot(responseDelay, [this, senderAddress, senderPort](){
+ QString message = QStringLiteral(
+ "HTTP/1.1 200 OK\r\n"
+ "LOCATION: http://") + localIpAddress + ":" + QString::number(tcpServer.serverPort()) + "/upnp.xml\r\n"
+ "EXT:\r\n"
+ "USN: uuid:" + this->uuid + "::" + this->searchTarget + "\r\n"
+ "SERVER: " + QSysInfo::productType() + "/" + QSysInfo::productVersion() + " UPnP/1.0 " + product + "/" + version + "\r\n"
+ "CACHE-CONTROL: max-age=86400\r\n"
+ "ST: " + this->searchTarget + "\r\n"
+ "DATE: " + DateRfc7231() + "\r\n"
+ "CONTENT-LENGTH: 0\r\n"
+ "\r\n";
+
+ QUdpSocket responseSocket;
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::processUdpData senderIp:" << senderAddress << message;
+ #endif
+ responseSocket.writeDatagram(message.toUtf8(), senderAddress, senderPort);
+ });
+}
+
+bool QUPnPRootDevice::processHttpGetRequest(QString urlUpper, QString &responseHead, QByteArray &responseBody)
+{
+ if (urlUpper == "/UPNP.XML")
+ {
+ responseBody = this->getUPnPxml().toUtf8();
+ responseHead += "content-type: text/xml; charset=utf-8\r\n";
+ return true;
+ }
+ else
+ {
+ QUPnPService *service = getService(urlUpper);
+ if (service) {
+ responseBody = service->getScpd().toUtf8();
+ responseHead += QStringLiteral(
+ "content-type: text/xml; charset=utf-8\r\n"
+ "server: ") + QSysInfo::productType() + "/" + QSysInfo::productVersion() + " UPnP/1.0 " + product + "/" + version + "\r\n";
+ return true;
+ }
+ }
+ return QMinimalHttpServer::processHttpGetRequest(urlUpper, responseHead, responseBody);
+}
+
+int QUPnPRootDevice::processHttpPostRequest(QString urlUpper, QByteArray &postBody, QString &responseHead, QByteArray &responseBody)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::processHttpPostRequest";
+ qDebug() << postBody;
+ #endif
+
+ QUPnPService *service = getService(urlUpper);
+ if (!service) {
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+ }
+
+ QDomDocument doc;
+ QString errorMsg; int errorLine; int errorColumn;
+ if (!doc.setContent(postBody, true, &errorMsg, &errorLine, &errorColumn)) {
+ #ifdef QT_DEBUG
+ qDebug() << "doc.setContent failed (" << errorLine << ":" << errorColumn << ") " << errorMsg;
+ #endif
+ responseHead = "HTTP/1.0 400 Bad Request\r\n";
+ return 400;
+ }
+
+ QDomElement envelope = doc.documentElement();
+ QDomNodeList bodies = envelope.elementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Body");
+ for (int bodyIdx = 0; bodyIdx < bodies.size(); bodyIdx++) {
+
+ QString actionName;
+
+ // iterate the RPC calls in the envelope
+ QDomNodeList RPCs = bodies.at(bodyIdx).toElement().childNodes();
+ for (int RPCIdx = 0; RPCIdx < RPCs.size(); RPCIdx++) {
+ if (!RPCs.at(RPCIdx).isElement())
+ continue;
+
+ actionName = RPCs.at(RPCIdx).toElement().localName();
+
+ // collect parameters
+ QMap<QString, QString> actionParameters;
+ QDomNodeList params = RPCs.at(RPCIdx).toElement().childNodes();
+ for (int paramIdx = 0; paramIdx < params.size(); paramIdx++) {
+ if (!params.at(paramIdx).isElement())
+ continue;
+
+ QString paramName = params.at(paramIdx).toElement().localName();
+ QString paramValue = "";
+ // get paramValue
+ QDomNodeList paramChildren = params.at(paramIdx).toElement().childNodes();
+ for (int paramChildIdx = 0; paramChildIdx < paramChildren.size(); paramChildIdx++)
+ if (paramChildren.at(paramChildIdx).isText())
+ paramValue = paramChildren.at(paramChildIdx).toText().data();
+
+ actionParameters[paramName] = paramValue;
+ }
+
+ // execute the RPC call
+ return service->executeRemoteProcedureCall(actionName, actionParameters, responseHead, responseBody);
+
+ }
+ }
+
+ return QMinimalHttpServer::processHttpPostRequest(urlUpper, postBody, responseHead, responseBody);
+}
+
+int QUPnPRootDevice::processHttpSubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::processHttpSubscribeRequest";
+ #endif
+
+ QUPnPService *service = getService(urlUpper);
+ if (!service) {
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+ }
+
+ return service->processHttpSubscribeRequest(requestLines, responseHead, responseBody);
+}
+
+int QUPnPRootDevice::processHttpUnsubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::processHttpUnsubscribeRequest";
+ #endif
+
+ QUPnPService *service = getService(urlUpper);
+ if (!service) {
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+ }
+
+ return service->processHttpUnsubscribeRequest(requestLines, responseHead, responseBody);
+}
+
+QString QUPnPRootDevice::createUuid(const QString &base)
+{
+ QString uuid;
+ if (base == QString()) {
+ uuid = QUuid::createUuid().toString(); // random uuid
+ uuid = uuid.mid(1, uuid.length()-2); // remove leading { and trailing }
+ } else {
+ uuid = QString(QCryptographicHash::hash(base.toUtf8(),QCryptographicHash::Sha1).toHex());
+ }
+
+ return uuid;
+}
+
+void QUPnPRootDevice::startListening(quint16 port)
+{
+ if (isListening())
+ return;
+
+ QMinimalHttpServer::startListening(port);
+
+ udpSocket.bind(QHostAddress::AnyIPv4, multicastPort, QUdpSocket::ReuseAddressHint);
+ udpSocket.joinMulticastGroup(multicastAddress);
+
+ // notify network via multicast
+ QString message = QStringLiteral(
+ "NOTIFY * HTTP/1.1\r\n"
+ "HOST: ") + multicastAddress.toString() + ":" + QString::number(multicastPort) + "\r\n"
+ "CACHE-CONTROL: max-age=86400\r\n"
+ "LOCATION: http://" + localIpAddress + ":" + QString::number(tcpServer.serverPort()) + "/upnp.xml\r\n"
+ "SERVER: " + QSysInfo::productType() + "/" + QSysInfo::productVersion() + " UPnP/1.0 " + product + "/" + version + "\r\n"
+ "NTS: ssdp:alive\r\n"
+ "NT: " + this->searchTarget + "\r\n"
+ "USN: uuid:" + this->uuid + "::" + this->searchTarget + "\r\n"
+ "\r\n";
+ QUdpSocket aliveSocket;
+ aliveSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, 4);
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::startListening " << message;
+ #endif
+ aliveSocket.writeDatagram(message.toUtf8(), multicastAddress, multicastPort);
+}
+
+void QUPnPRootDevice::stopListening()
+{
+ if (!isListening())
+ return;
+
+ // notify network via multicast
+ QString message = QStringLiteral(
+ "NOTIFY * HTTP/1.1\r\n"
+ "HOST: ") + multicastAddress.toString() + ":" + QString::number(multicastPort) + "\r\n"
+ "NT: " + this->searchTarget + "\r\n"
+ "NTS: ssdp:byebye\r\n"
+ "USN: uuid:" + this->uuid + "::" + this->searchTarget + "\r\n"
+ "SERVER: " + QSysInfo::productType() + "/" + QSysInfo::productVersion() + " UPnP/1.0 " + product + "/" + version + "\r\n"
+ "DATE: " + DateRfc7231() + "\r\n"
+ "CONTENT-LENGTH: 0\r\n"
+ "\r\n";
+ QUdpSocket byebyeSocket;
+ byebyeSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, 4);
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPRootDevice::stopListening " << message;
+ #endif
+ byebyeSocket.writeDatagram(message.toUtf8(), multicastAddress, multicastPort);
+
+ udpSocket.leaveMulticastGroup(multicastAddress);
+ udpSocket.close();
+ QMinimalHttpServer::stopListening();
+}
+
+void QUPnPRootDevice::addIcon(const QString &filename)
+{
+ QFileInfo info(filename);
+ QString nameonly = QString("/") + info.fileName().toUpper();
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QByteArray data = file.readAll();
+ file.close();
+ this->addFile(nameonly, data);
+
+ QImage img;
+ img.load(filename);
+ icons[nameonly] = img;
+
+ if (isListening()) {
+ stopListening();
+ startListening();
+ }
+}
+
+void QUPnPRootDevice::addService(QUPnPService *service)
+{
+ QString id = service->identifier.toUpper();
+ if (this->services.contains(id))
+ return;
+ service->rootdevice = this;
+ this->services[id] = service;
+
+ if (isListening()) {
+ stopListening();
+ startListening();
+ }
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.h
new file mode 100644
index 0000000..10d47ad
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnprootdevice.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUPNPROOTDEVICE_H
+#define QUPNPROOTDEVICE_H
+
+#include <QObject>
+#include <QUdpSocket>
+#include <QHostAddress>
+#include <QNetworkInterface>
+#include <QTimer>
+#include <QUuid>
+#include <QFileInfo>
+#include <QImage>
+#include <QtXml/QtXml>
+
+#include "qminimalhttpserver.h"
+#include "qupnpservice.h"
+
+class QUPnPRootDevice : public QMinimalHttpServer
+{
+ Q_OBJECT
+ friend class QUPnPService;
+ friend class MainWindow;
+
+private:
+ static QList<QUPnPRootDevice*> allUPnPRootDevices;
+
+protected:
+ QString manufacturer = "The Qt Company GmbH";
+ QString manufacturerURL = "https://qt.io";
+ QString product = "Qt UPnP-to-KNX Bridge";
+ QString version = "0.1";
+ QString uuid = "";
+ QString searchTarget = "upnp:rootdevice";
+ QMap<QString, QImage> icons;
+ QMap<QString, QUPnPService*> services;
+
+ QString localIpAddress = "";
+ QUdpSocket udpSocket;
+ virtual QString getUPnPxml();
+ virtual QUPnPService *getService(const QString &urlUpper);
+ void onUdpDataReceived();
+ virtual void processUdpData(const QString &data, QHostAddress senderAddress, quint16 senderPort);
+ bool processHttpGetRequest(QString urlUpper, QString &responseHead, QByteArray &responseBody) override;
+ int processHttpPostRequest(QString urlUpper, QByteArray &postBody, QString &responseHead, QByteArray &responseBody) override;
+ int processHttpSubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody) override;
+ int processHttpUnsubscribeRequest(QString urlUpper, QStringList &requestLines, QString &responseHead, QByteArray &responseBody) override;
+
+ static const QHostAddress multicastAddress;
+ static const quint16 multicastPort;
+ static QString createUuid(const QString &base = QString());
+
+public:
+ explicit QUPnPRootDevice(QObject *parent, const QString &searchTarget, const QString &name = "upnp:rootdevice");
+ ~QUPnPRootDevice();
+
+ void startListening(quint16 port = 0);
+ void stopListening();
+ void addIcon(const QString &filename);
+ void addService(QUPnPService* service);
+ static void stopAllUPnPRootDevices();
+
+signals:
+
+};
+
+#endif // QUPNPROOTDEVICE_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.cpp
new file mode 100644
index 0000000..6e09ed7
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qupnpservice.h"
+#include "qupnprootdevice.h"
+
+QUPnPService::QUPnPService(QObject *parent, QString identifier)
+ : QObject(parent)
+{
+ this->identifier = identifier;
+}
+
+QUPnPService::~QUPnPService()
+{
+}
+
+QString QUPnPService::upnpServiceListEntry()
+{
+ return QStringLiteral(
+ "<service>"
+ "<serviceType>urn:schemas-upnp-org:service:") + identifier + ":1</serviceType>"
+ //"<serviceId>urn:upnp-org:serviceId:" + identifier + ":1</serviceId>"
+ "<serviceId>" + identifier + "</serviceId>"
+ "<SCPDURL>/" + identifier + "/scpd.xml</SCPDURL>"
+ "<controlURL>/" + identifier + "/Control</controlURL>"
+ "<eventSubURL>/" + identifier + "/Events</eventSubURL>"
+ "</service>";
+}
+
+int QUPnPService::executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(actionName);
+ Q_UNUSED(actionParams);
+ Q_UNUSED(responseHead);
+ Q_UNUSED(responseBody);
+ responseHead = "HTTP/1.0 404 Not Found\r\n";
+ return 404;
+}
+
+int QUPnPService::processHttpSubscribeRequest(QStringList &lines, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(responseBody);
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPService::processHttpSubscribeRequest";
+ #endif
+
+ QUPnPServiceSubscription subscription;
+ QString timeout = "0";
+ for (int i = 1; i < lines.size(); i++) {
+ if (lines.at(i).startsWith("CALLBACK:", Qt::CaseInsensitive)) {
+ QString url = lines.at(i).mid(9).trimmed();
+ if (url.startsWith("<") && url.endsWith(">"))
+ url = url.mid(1, url.size()-2);
+ subscription.url = QUrl(url);
+ } else if (lines.at(i).startsWith("TIMEOUT:", Qt::CaseInsensitive)) {
+ timeout = lines.at(i).mid(8).trimmed();
+ } else if (lines.at(i).startsWith("SID:", Qt::CaseInsensitive)) {
+ // renewing a subscription
+ subscription.uuid = lines.at(i).mid(4).trimmed();
+ }
+ }
+
+ if (timeout.startsWith("SECOND-", Qt::CaseInsensitive))
+ timeout = timeout.mid(7).trimmed();
+ bool ok = false;
+ int iTimeout = timeout.toInt(&ok);
+ subscription.timeoutTime = QDateTime::currentDateTime().addSecs(iTimeout);
+
+ if (!ok || !subscription.url.isValid()) {
+ responseHead = "HTTP/1.0 400 Bad Request\r\n";
+ return 400;
+ }
+
+ // no SID header => new subscription => new SID
+ if (subscription.uuid == "") {
+ subscription.uuid = QUuid::createUuid().toString();
+ subscription.uuid = QStringLiteral("uuid:") + subscription.uuid.mid(1, subscription.uuid.size()-2);
+
+ subscriptions[subscription.uuid] = subscription;
+
+ // delay the notification so that the "HTTP/1.1 200 OK" message comes first
+ QString uuid = subscription.uuid;
+ QTimer::singleShot(50, [uuid, this](){
+ if (subscriptions.contains(uuid))
+ onNewSubscriber(subscriptions[uuid]);
+ });
+
+ } else {
+ // only update the timeout. seq and url must stay the same, uuid would stay the same anyways
+ if (subscriptions.contains(subscription.uuid)) {
+ responseHead = "HTTP/1.0 412 Precondition Failed\r\n";
+ return 412;
+ }
+ subscriptions[subscription.uuid].timeoutTime = subscription.timeoutTime;
+ }
+
+ responseHead = responseHead
+ + "SERVER: " + QSysInfo::productType() + "/" + QSysInfo::productVersion() + " UPnP/1.0 " + rootdevice->product + "/" + rootdevice->version + "\r\n"
+ + "SID: " + subscription.uuid + "\r\n"
+ + "TIMEOUT: Second-" + QString::number(iTimeout) + "\r\n";
+
+ return 200;
+}
+
+int QUPnPService::processHttpUnsubscribeRequest(QStringList &lines, QString &responseHead, QByteArray &responseBody)
+{
+ Q_UNUSED(responseBody);
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPService::processHttpUnsubscribeRequest";
+ #endif
+
+ // find SID: header
+ QString SubscriptionUuid;
+ for (int i = 1; i < lines.size(); i++)
+ if (lines.at(i).startsWith("SID:", Qt::CaseInsensitive))
+ SubscriptionUuid = lines.at(i).mid(4).trimmed();
+ if (SubscriptionUuid == "" || !subscriptions.contains(SubscriptionUuid)) {
+ responseHead = "HTTP/1.0 412 Precondition Failed\r\n";
+ return 412;
+ }
+
+ subscriptions.remove(SubscriptionUuid);
+ return 200;
+}
+
+bool QUPnPService::notifySubscriber(QUPnPServiceSubscription &subscription, const QString &propertyName, const QString &propertyValue)
+{
+ QByteArray notificationBody = (QStringLiteral(
+ "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">"
+ "<e:property>"
+ "<") + propertyName + ">" + propertyValue + "</" + propertyName + ">"
+ "</e:property>"
+ "</e:propertyset>").toUtf8();
+
+ QString notification = QStringLiteral(
+ "NOTIFY ") + subscription.url.path() + " HTTP/1.1\r\n"
+ "HOST: " + subscription.url.host();
+ if (subscription.url.port() > 0)
+ notification += QStringLiteral(":") + QString::number(subscription.url.port());
+ notification += "\r\n"
+ "CONTENT-TYPE: text/xml; charset=utf-8\r\n"
+ "NT: upnp:event\r\n"
+ "NTS: upnp:propchange\r\n"
+ "CONTENT-LENGTH: " + QString::number(notificationBody.size()) + "\r\n"
+ "SID: " + subscription.uuid + "\r\n"
+ "SEQ: " + QString::number(subscription.sequenceNumber) + "\r\n"
+ "CONNECTION: close\r\n"
+ "\r\n";
+
+ if (subscription.sequenceNumber >= UINT_MAX)
+ subscription.sequenceNumber = 1; // not 0!
+ else
+ subscription.sequenceNumber++;
+
+ QByteArray message = notification.toUtf8();
+ message.append(notificationBody);
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPService::notifySubscriber: " << message;
+ #endif
+
+ QTcpSocket notificationSocket;
+ notificationSocket.connectToHost(subscription.url.host(), subscription.url.port(80));
+ if (!notificationSocket.waitForConnected(10000)) {
+ qDebug() << "QUPnPService::notifySubscriber: ERROR could not connect to host";
+ return false;
+ }
+
+ notificationSocket.write(message);
+ notificationSocket.waitForReadyRead(30000); // See UPnP specification, chapter 4.2.1
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPService::notifySubscriber RESPONSE: " << message;
+ #endif
+ return true;
+}
+
+void QUPnPService::notifyPropertyChanged(const QString &propertyName, const QString &propertyValue)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPService::notifyPropertyChanged";
+ #endif
+ QDateTime now = QDateTime::currentDateTime();
+ QList<QString> expiredSubscriptions;
+
+ for (QString subscriptionKey : subscriptions.keys()) {
+ QUPnPServiceSubscription &subscription = subscriptions[subscriptionKey];
+ bool mustRemove = true;
+ if (now <= subscription.timeoutTime)
+ mustRemove = !notifySubscriber(subscription, propertyName, propertyValue);
+ if (mustRemove)
+ expiredSubscriptions.push_back(subscriptionKey);
+ }
+
+ for (QString expiredKey : expiredSubscriptions)
+ subscriptions.remove(expiredKey);
+}
+
+
+
+QUPnPBooleanService::QUPnPBooleanService(QObject *parent, QString identifier)
+ : QUPnPService(parent, identifier)
+{
+}
+
+bool QUPnPBooleanService::doSetState(bool state)
+{
+// if (state == this->state)
+// return false;
+ this->state = state;
+ return true;
+}
+
+void QUPnPBooleanService::setState(bool state)
+{
+ if (doSetState(state)) {
+ notifyPropertyChanged("state", state?"1":"0");
+ emit this->stateChanged(state);
+ } else {
+ emit this->stateChangeFailed();
+ }
+}
+
+bool QUPnPBooleanService::getState()
+{
+ return state;
+}
+
+QString QUPnPBooleanService::getScpd()
+{
+ return QStringLiteral(
+ "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"
+ "<specVersion>"
+ "<major>1</major>"
+ "<minor>0</minor>"
+ "</specVersion>"
+
+ "<actionList>"
+ "<action>"
+ "<name>setState</name>"
+ "<argumentList>"
+ "<argument>"
+ "<name>newState</name>"
+ "<relatedStateVariable>state</relatedStateVariable>"
+ "<direction>in</direction>"
+ "</argument>"
+ "</argumentList>"
+ "</action>"
+ "</actionList>"
+
+ "<serviceStateTable>"
+ "<stateVariable sendEvents=\"yes\">"
+ "<name>state</name>"
+ "<dataType>boolean</dataType>"
+ "<defaultValue>") + (getState()?"1":"0") + "</defaultValue>"
+ "</stateVariable>"
+ "</serviceStateTable>"
+ "</scpd>";
+}
+
+int QUPnPBooleanService::executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QUPnPBooleanService::executeRemoteProcedureCall";
+ #endif
+
+ bool ok = false;
+ int newStateValue = actionParams["newState"].toInt(&ok);
+ if (actionName.toUpper() != "SETSTATE" || newStateValue < 0 || 1 < newStateValue || !ok) {
+ responseHead = "HTTP/1.0 400 Bad Request\r\n";
+ return 400;
+ }
+
+ this->setState(newStateValue == 1);
+ responseHead = QStringLiteral(
+ "HTTP/1.0 200 OK\r\n"
+ "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n");
+ responseBody = (QStringLiteral(
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>"
+ "<u:") + actionName + "Response xmlns:u=\"urn:schemas-upnp-org:service:" + identifier +":1\">"
+ "</u:" + actionName + "Response>"
+ "</s:Body>"
+ "</s:Envelope>").toUtf8();
+ return 200;
+}
+
+void QUPnPBooleanService::onNewSubscriber(QUPnPServiceSubscription &subscription)
+{
+ this->notifySubscriber(subscription, "state", getState()?"1":"0");
+}
+
+
+
+QUPnPBooleanServiceProxy::QUPnPBooleanServiceProxy(QObject *parent, QUPnPBooleanService *target, QString identifier)
+ : QUPnPBooleanService(parent, identifier)
+ , m_target(target)
+{
+ if (target) {
+ connect(target, &QUPnPBooleanService::stateChanged, [this](bool state){
+ this->notifyPropertyChanged("state", state?"1":"0");
+ emit stateChanged(state);
+ });
+ connect(target, &QUPnPBooleanService::stateChangeFailed, [this](){
+ emit stateChangeFailed();
+ });
+ }
+}
+
+void QUPnPBooleanServiceProxy::setState(bool state)
+{
+ if (m_target)
+ m_target->setState(state);
+}
+
+bool QUPnPBooleanServiceProxy::getState()
+{
+ if (!m_target)
+ return false;
+ return m_target->getState();
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.h
new file mode 100644
index 0000000..fa3f51a
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qupnpservice.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUPNPSERVICE_H
+#define QUPNPSERVICE_H
+
+#include <QObject>
+#include <QTcpSocket>
+#include <QtXml/QtXml>
+
+
+class QUPnPServiceSubscription
+{
+ friend class QUPnPService;
+ QString uuid;
+ QUrl url;
+ QDateTime timeoutTime;
+ quint32 sequenceNumber = 0;
+};
+class QUPnPRootDevice;
+
+class QUPnPService : public QObject
+{
+ Q_OBJECT
+ friend class QUPnPRootDevice;
+ friend class QVirtualBelkinWeMo;
+
+protected:
+ QUPnPRootDevice *rootdevice;
+ QString identifier;
+ QMap<QString, QUPnPServiceSubscription> subscriptions;
+ virtual QString upnpServiceListEntry();
+ virtual QString getScpd() = 0;
+ virtual int executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody);
+ virtual int processHttpSubscribeRequest(QStringList &requestLines, QString &responseHead, QByteArray &responseBody);
+ virtual int processHttpUnsubscribeRequest(QStringList &requestLines, QString &responseHead, QByteArray &responseBody);
+ void notifyPropertyChanged(const QString &propertyName, const QString &propertyValue);
+ bool notifySubscriber(QUPnPServiceSubscription &subscription, const QString &propertyName, const QString &propertyValue);
+ virtual void onNewSubscriber(QUPnPServiceSubscription &subscription) = 0;
+
+public:
+ explicit QUPnPService(QObject *parent = nullptr, QString identifier=QString());
+ virtual ~QUPnPService();
+ Q_DISABLE_COPY(QUPnPService)
+};
+
+
+class QUPnPBooleanService : public QUPnPService
+{
+ Q_OBJECT
+
+protected:
+ bool state = false;
+ virtual bool doSetState(bool state);
+ QString getScpd() override;
+ int executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody) override;
+ void onNewSubscriber(QUPnPServiceSubscription &subscription) override;
+
+public:
+ explicit QUPnPBooleanService(QObject *parent = nullptr, QString identifier=QString());
+ virtual void setState(bool state);
+ virtual bool getState();
+
+signals:
+ void stateChanged(bool newState);
+ void stateChangeFailed();
+};
+
+
+class QUPnPBooleanServiceProxy : public QUPnPBooleanService
+{
+ Q_OBJECT
+
+protected:
+ QUPnPBooleanService *m_target;
+
+public:
+ explicit QUPnPBooleanServiceProxy(QObject *parent, QUPnPBooleanService *target, QString identifier=QString());
+ void setState(bool state) override;
+ bool getState() override;
+};
+
+#endif // QUPNPSERVICE_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.cpp b/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.cpp
new file mode 100644
index 0000000..cb92db8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Parts of this work are derived from makermusings fauxmo, see
+// http://www.makermusings.com/2015/07/18/virtual-wemo-code-for-amazon-echo/
+// https://github.com/makermusings/fauxmo
+// commit 54e00be77552fba7b177866f55cf89d017c57dc6
+// provided under the terms of
+
+/****************************************************************************
+The MIT License (MIT)
+
+Copyright (c) 2015
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+****************************************************************************/
+
+#include "qvirtualbelkinwemo.h"
+#include "qupnpservice.h"
+
+
+QVirtualBelkinWeMo::QVirtualBelkinWeMo(QObject *parent, const QString &name)
+ : QUPnPRootDevice(parent, name, QStringLiteral("urn:Belkin:device:**"))
+{
+ this->service = new QVirtualBelkinWeMoService(this);
+ this->addService(this->service);
+
+}
+
+QString QVirtualBelkinWeMo::getUPnPxml()
+{
+ QString upnp_xml = QStringLiteral(
+ "<?xml version=\"1.0\"?>"
+ "<root>"
+ "<device>"
+ "<deviceType>urn:Belkin:device:")+ deviceType +":1</deviceType>"
+ "<friendlyName>" + this->product + "</friendlyName>"
+ "<manufacturer>Belkin International Inc.</manufacturer>"
+ "<modelName>Emulated Socket</modelName>"
+ "<modelNumber>3.1415</modelNumber>"
+ "<UDN>uuid:Socket-1_0-" + this->uuid + "</UDN>";
+
+ // icons
+ if (icons.size() > 0) {
+ upnp_xml += "<iconList>";
+ for (QString iconKey : icons.keys()) {
+ QImage icon = icons[iconKey];
+ upnp_xml += QStringLiteral(
+ "<icon>") +
+ "<mimetype>" + httpFileMimeTypes[iconKey] + "</mimetype>"
+ "<width>" + QString::number(icon.width()) + "</width>"
+ "<height>" + QString::number(icon.height()) + "</height>"
+ "<depth>" + QString::number(icon.depth()) + "</depth>"
+ "<url>" + iconKey + "</url>"
+ "</icon>";
+ }
+ upnp_xml += "</iconList>";
+ }
+
+ // services
+ if (services.size() > 0) {
+ upnp_xml += "<serviceList>";
+ for (auto service : services)
+ upnp_xml += service->upnpServiceListEntry();
+ upnp_xml += "</serviceList>";
+ }
+
+ upnp_xml +=
+ "</device>"
+ "</root>";
+
+ return upnp_xml;
+}
+
+QUPnPService *QVirtualBelkinWeMo::getService(const QString &urlUpper)
+{
+ Q_UNUSED(urlUpper);
+ return service;
+}
+
+QVirtualBelkinWeMoService::QVirtualBelkinWeMoService(QObject *parent)
+ : QUPnPBooleanService(parent, "SwitchPower")
+{
+
+}
+
+QString QVirtualBelkinWeMoService::upnpServiceListEntry()
+{
+ return QStringLiteral(
+ "<service>"
+ "<serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>"
+ "<serviceId>") + identifier + "</serviceId>"
+ "<SCPDURL>/" + identifier + "/scpd.xml</SCPDURL>"
+ "<controlURL>/upnp/control</controlURL>"
+ "</service>";
+}
+
+QString QVirtualBelkinWeMoService::getScpd()
+{
+ return QStringLiteral(
+ "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"
+ "<specVersion>"
+ "<major>1</major>"
+ "<minor>0</minor>"
+ "</specVersion>"
+
+ "<actionList>"
+ "<action>"
+ "<name>SetBinaryState</name>"
+ "<argumentList>"
+ "<argument>"
+ "<name>BinaryState</name>"
+ "<relatedStateVariable>state</relatedStateVariable>"
+ "<direction>in</direction>"
+ "</argument>"
+ "</argumentList>"
+ "</action>"
+
+ "<action>"
+ "<name>GetBinaryState</name>"
+ "<argumentList>"
+ "<argument>"
+ "<name>BinaryState</name>"
+ "<relatedStateVariable>state</relatedStateVariable>"
+ "<direction>out</direction>"
+ "</argument>"
+ "</argumentList>"
+ "</action>"
+ "</actionList>"
+
+ "<serviceStateTable>"
+ "<stateVariable sendEvents=\"no\">"
+ "<name>state</name>"
+ "<dataType>boolean</dataType>"
+ "<defaultValue>") + (getState()?"1":"0") + "</defaultValue>"
+ "</stateVariable>"
+ "</serviceStateTable>"
+ "</scpd>";
+}
+
+int QVirtualBelkinWeMoService::executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody)
+{
+ #ifdef QT_DEBUG
+ qDebug() << "QVirtualBelkinWeMoService::executeRemoteProcedureCall " << actionName << actionParams;
+ #endif
+
+ if (actionName.toUpper() == "SETBINARYSTATE") {
+ bool ok = false;
+ int newStateValue = actionParams["BinaryState"].toInt(&ok);
+ if (newStateValue < 0 || 1 < newStateValue || !ok) {
+ responseHead = "HTTP/1.0 400 Bad Request\r\n";
+ return 400;
+ }
+
+ this->setState(newStateValue == 1);
+ } else if (actionName.toUpper() != "GETBINARYSTATE") {
+ responseHead = "HTTP/1.0 400 Bad Request\r\n";
+ return 400;
+ }
+
+ responseHead = QStringLiteral(
+ "HTTP/1.0 200 OK\r\n"
+ "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n");
+ responseBody = (QStringLiteral(
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>"
+ "<u:") + actionName + "Response xmlns:u=\"urn:schemas-upnp-org:service:" + identifier +":1\">"
+ "<BinaryState>" + (getState() ? "1" : "0") + "</BinaryState>"
+ "</u:" + actionName + "Response>"
+ "</s:Body>"
+ "</s:Envelope>").toUtf8();
+ return 200;
+}
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.h
new file mode 100644
index 0000000..852444c
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/qvirtualbelkinwemo.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIRTUALBELKINWEMO_H
+#define QVIRTUALBELKINWEMO_H
+
+#include "qupnprootdevice.h"
+
+class QVirtualBelkinWeMoService : public QUPnPBooleanService
+{
+ Q_OBJECT
+
+protected:
+ QString upnpServiceListEntry();
+ QString getScpd();
+ int executeRemoteProcedureCall(QString actionName, QMap<QString, QString> &actionParams, QString &responseHead, QByteArray &responseBody) override;
+
+public:
+ explicit QVirtualBelkinWeMoService(QObject *parent = nullptr);
+};
+
+class QVirtualBelkinWeMo : public QUPnPRootDevice
+{
+ Q_OBJECT
+ friend class MainWindow;
+private:
+
+protected:
+ QVirtualBelkinWeMoService *service;
+ QString getUPnPxml() override;
+
+
+public:
+ QVirtualBelkinWeMo(QObject *parent, const QString &name);
+ QUPnPService *getService(const QString &urlUpper) override;
+ QString deviceType = "controllee";
+};
+
+#endif // QVIRTUALBELKINWEMO_H
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/readme.md b/tradeshow/knx-demo/3d-Alexa-knx-demo/readme.md
new file mode 100644
index 0000000..48553f5
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/readme.md
@@ -0,0 +1,15 @@
+# Qt 3D Studio Home Automation Demo
+
+This demo application is created with Qt 3D Studio and Qt Quick.
+It uses a Qt 3D presentation (.uip file) to show what home automation application could look like.
+The demo has controls to change lighting and temperature (represented as color) of the rooms.
+
+![Home Automation Demo](/HomeAutomation/images/home-automation-demo.png)
+
+The application is designed to be used with Pixel C, but it also has basic scaling in place.
+By default the screen size is used as the main application window size. Uncommenting FIXEDWINDOW
+definition from main.cpp will force the main application window to be of size 1280x900.
+
+Config variable KNX_BOARD can be used to compile the application so that it controls the
+KNX board.
+
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/House.import b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/House.import
new file mode 100644
index 0000000..d1aad35
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/House.import
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" >
+ <Model id="Ground" name="Ground" orientation="Right Handed" position="-0.957248 -0.10826 -2.79746" rotation="0 -0 0" rotationorder="XYZr" scale="1.73739 1 1.00748" sourcepath=".\meshes\Ground.mesh#1" >
+ <Material id="phong1" name="phong1" blendmode="Normal" diffuse="0.233766 0.233766 0.233766" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="roof1" name="roof1" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\roof1.mesh#1" >
+ <Material id="BaseWall" name="BaseWall" blendmode="Normal" diffuse="0.552284 0.552284 0.552284" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ <Material id="roof" name="roof" blendmode="Normal" diffuse="0.0609137 0.0609137 0.0609137" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ <Material id="lambert1" name="lambert1" blendmode="Normal" diffuse="1 1 1" emissivepower="0" opacity="100" specularamount="0" />
+ </Model>
+ <Group id="Group_HeatAreas" name="Group_HeatAreas" orientation="Right Handed" position="0 5.53285 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" >
+ <Model id="Heat_MasterBedroom" name="Heat_MasterBedroom" orientation="Right Handed" position="-6.01453 0.0613521 -9.90316" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_MasterBedroom.mesh#1" >
+ <Material id="masterbedroomheat" name="masterbedroomheat" blendmode="Normal" diffuse="0.15472 0.15096 0.14256" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_Entrance" name="Heat_Entrance" orientation="Right Handed" position="0.0827332 1.40091 -12.9964" rotation="8.53363 -0 0" rotationorder="XYZr" scale="0.852158 1 0.900558" sourcepath=".\meshes\Heat_Entrance.mesh#1" >
+ <Material id="entrance" name="entrance" blendmode="Normal" diffuse="0.519797 0.519797 0.519797" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_BedRoom" name="Heat_BedRoom" orientation="Right Handed" position="6.03439 1.73831 -10.6134" rotation="7.55792 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_BedRoom.mesh#1" >
+ <Material id="bedroom" name="bedroom" blendmode="Normal" diffuse="0.24488 0.388 0.46264" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_DressRoom" name="Heat_DressRoom" orientation="Right Handed" position="8.02201 2.41339 -5.07462" rotation="8.34257 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_DressRoom.mesh#1" >
+ <Material id="dressroom" name="dressroom" blendmode="Normal" diffuse="0.714721 0.714721 0.714721" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_Toilet" name="Heat_Toilet" orientation="Right Handed" position="3.90588 2.58136 -5.05141" rotation="5.57327 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_Toilet.mesh#1" >
+ <Material id="toilet" name="toilet" blendmode="Normal" diffuse="0.19208 0.24752 0.37672" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_StoreRoom" name="Heat_StoreRoom" orientation="Right Handed" position="2.97044 0.814303 -17.1022" rotation="8.02365 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_StoreRoom.mesh#1" >
+ <Material id="storeroom" name="storeroom" blendmode="Normal" diffuse="0.166497 0.166497 0.166497" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_Sauna" name="Heat_Sauna" orientation="Right Handed" position="-7.99717 0.0613521 7.72293" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_Sauna.mesh#1" >
+ <Material id="sauna1" name="sauna1" blendmode="Normal" diffuse="0.24984 0.24984 0.24984" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_BathRoom" name="Heat_BathRoom" orientation="Right Handed" position="-8.61282 1.1588 -1.06378" rotation="0 -0 0" rotationorder="XYZr" scale="1.04514 1 1" sourcepath=".\meshes\Heat_BathRoom.mesh#1" >
+ <Material id="bathroom" name="bathroom" blendmode="Normal" diffuse="0.4 0.4 0.4" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ <Model id="Heat_LivingRoom" name="Heat_LivingRoom" orientation="Right Handed" position="2.34465 3.80193 4.35739" rotation="7.88151 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Heat_LivingRoom.mesh#1" >
+ <Material id="livingroom" name="livingroom" blendmode="Normal" diffuse="0.24984 0.23336 0.16168" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" />
+ </Model>
+ </Group>
+ <Group id="Group_house" name="Group_house" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" >
+ <Model id="house1" name="house1" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\house1.mesh#1" >
+ <Material id="house2" name="house2" blendmode="Normal" diffuse="1 1 1" diffusemap="house2_diffusemap" emissivepower="0" opacity="100" specularamount="0" specularroughness="20" >
+ <Image id="house2_diffusemap" name="house2_diffusemap" sourcepath=".\maps\houseShape.png" />
+ </Material>
+ </Model>
+ </Group>
+ <Model id="Windows" name="Windows" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath=".\meshes\Windows.mesh#1" >
+ <Material id="Window" name="Window" blendmode="Normal" diffuse="0.35152 0.66672 0.74704" emissivepower="0" opacity="100" specularamount="0" specularroughness="12.1818" />
+ </Model>
+ </Group>
+ </Graph>
+ <Import SrcFile="..\..\House\House.fbx" ImageDir="Images" MeshDir="Meshes" >
+ <Image >
+ <Source >.\houseShape.png</Source>
+ <Dest >.\maps\houseShape.png</Dest>
+ </Image>
+ <Mesh >
+ <Source >Heat_BathRoom</Source>
+ <Dest >.\meshes\Heat_BathRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_Sauna</Source>
+ <Dest >.\meshes\Heat_Sauna.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_BedRoom</Source>
+ <Dest >.\meshes\Heat_BedRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Ground</Source>
+ <Dest >.\meshes\Ground.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_Toilet</Source>
+ <Dest >.\meshes\Heat_Toilet.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_StoreRoom</Source>
+ <Dest >.\meshes\Heat_StoreRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_LivingRoom</Source>
+ <Dest >.\meshes\Heat_LivingRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >house1</Source>
+ <Dest >.\meshes\house1.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_DressRoom</Source>
+ <Dest >.\meshes\Heat_DressRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Windows</Source>
+ <Dest >.\meshes\Windows.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_MasterBedroom</Source>
+ <Dest >.\meshes\Heat_MasterBedroom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >roof1</Source>
+ <Dest >.\meshes\roof1.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_Entrance</Source>
+ <Dest >.\meshes\Heat_Entrance.mesh</Dest>
+ </Mesh>
+ </Import>
+ </Project>
+</UIP>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/maps/houseShape.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/maps/houseShape.png
new file mode 100644
index 0000000..41707e1
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/maps/houseShape.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f51993d6c61e765bda9ec72e716512ada65dd95a3bad97518648448b85263ac6
+size 4005995
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Ground.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Ground.mesh
new file mode 100644
index 0000000..fc4f211
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Ground.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5c4af427e71594fd244ae2b5d712c662e337a42cb05c372df3a770d4bad49a44
+size 580
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BathRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BathRoom.mesh
new file mode 100644
index 0000000..4feca59
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BathRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6f39301d0409dba0ed768afbd284127ea71a88b1be5a40a5d872bc358a4d28e4
+size 944
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BedRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BedRoom.mesh
new file mode 100644
index 0000000..ded60ae
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_BedRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:800b8155ee25712ad65a4529617b10a4d350fd3f8352a8940dbed0aac4afa004
+size 584
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_DressRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_DressRoom.mesh
new file mode 100644
index 0000000..6f1c335
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_DressRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c0a8e5bcf3fafbe637e7f50e7f7929979da52f8c687392ce64dbcb54329528eb
+size 588
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Entrance.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Entrance.mesh
new file mode 100644
index 0000000..4d2ad7d
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Entrance.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c59c5d3eb5ea7ff8fdd83e77ed87a0241f72fce9c05f1be23e6246ac23b98dd9
+size 584
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_LivingRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_LivingRoom.mesh
new file mode 100644
index 0000000..6ba80a8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_LivingRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4f460eb3b33365d287ec7d6e07d05203ff7f4d1076ffc667847daabe29726519
+size 2376
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_MasterBedroom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_MasterBedroom.mesh
new file mode 100644
index 0000000..ebea101
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_MasterBedroom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:75060f0f0e828a43ff95594c58fde213c50f08fad09e2fc1442cbce61004fa0d
+size 852
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Sauna.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Sauna.mesh
new file mode 100644
index 0000000..6e6e089
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Sauna.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8b3cdd7103b6ad0582242f991f82e66d7f40f871174ab41ba16f7d5e2df1f1c3
+size 580
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_StoreRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_StoreRoom.mesh
new file mode 100644
index 0000000..53d7234
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_StoreRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6d7260110eac2557697a9021ac0a1b287969fce3aa0fa041f5b7ad66684abcc2
+size 588
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Toilet.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Toilet.mesh
new file mode 100644
index 0000000..2c9efe1
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Heat_Toilet.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:03fbf8872237fa58910e8d92b674ef6061f7d24f6741f5038b35796edabc2ddb
+size 580
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Windows.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Windows.mesh
new file mode 100644
index 0000000..a36ec89
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/Windows.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:667333174e964b7cb50738c62abe5013d94e77dc7d8f503cacdcffb09ae97b0c
+size 4592
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/house1.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/house1.mesh
new file mode 100644
index 0000000..ed2da37
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/house1.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9c4dca286b17a72672cc317de811befd0ec5ba183514ecd5e88db00e2dd15375
+size 284484
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/roof1.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/roof1.mesh
new file mode 100644
index 0000000..3f77b0c
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/House/meshes/roof1.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13f329118e118749595ac1751e7de7bf45eb1bcc058bf95b2f420f367a9c5774
+size 19180
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/houseStudio.uip b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/houseStudio.uip
new file mode 100644
index 0000000..f64204e
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/houseStudio.uip
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fc30878cd2956d3007ca060c3e40e0d7454b218453c92a0caf8c3c6c0d22cf01
+size 279
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BathroomLightmap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BathroomLightmap.png
new file mode 100644
index 0000000..94be8b5
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BathroomLightmap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7dd6647023eee217a16ef63c8418ff29bab5005f77e9e0153c46fdc42cfe5ae0
+size 203590
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BedRoomLightmap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BedRoomLightmap.png
new file mode 100644
index 0000000..7602e32
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/BedRoomLightmap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3c7713b2b823a6d46f14459dfa8b9db2f9efe8928e869474b241e0b36ec7394b
+size 70519
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/EntranceLightmap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/EntranceLightmap.png
new file mode 100644
index 0000000..c4b4d44
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/EntranceLightmap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d5afdc5d67400592ae384d5c1c91d1ec3487181455ec445cb88015312b78ce08
+size 41621
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Ground.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Ground.png
new file mode 100644
index 0000000..a0440f7
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Ground.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aa0488d336670f297721d8fa05ba9048b7b9cebe889cd4e712fe46c6e938063b
+size 77518
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseGroundOpacitymap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseGroundOpacitymap.png
new file mode 100644
index 0000000..ac42dbb
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseGroundOpacitymap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ab5cf08c8d3e75e0ef547402d0327232ff4210c19fd3d6cb2806f04f2dfc6c6
+size 76323
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.jpg b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.jpg
new file mode 100644
index 0000000..fa9d021
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fa9683142d3954dc32a6bf9307f860d45bed3b7e9d983d5051b54219cf43fe42
+size 3459775
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.png
new file mode 100644
index 0000000..316661d
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/HouseTexture.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:071d192dd3f95d31ae042ae64dfcb02e56da64237587466420a5a8dec1a0f7ce
+size 14132813
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/LivingRoomLightMap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/LivingRoomLightMap.png
new file mode 100644
index 0000000..8e9b7d1
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/LivingRoomLightMap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:520dbc10ec404e7c83a4b52c6533a5a8dafbbbb74082bdb053156a270af6f6df
+size 552205
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/MasterBedroomLightmap.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/MasterBedroomLightmap.png
new file mode 100644
index 0000000..3b0acb1
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/MasterBedroomLightmap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:92e32450eaf3ff1519da5e4e3ff274a46921f8e35a296f9a9d67cb34c47e4d41
+size 113642
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/OpenfootageNET_Pinzgau-512.hdr b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/OpenfootageNET_Pinzgau-512.hdr
new file mode 100644
index 0000000..2fd25a6
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/OpenfootageNET_Pinzgau-512.hdr
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e0baf00208f32e5f037c2f9433b3ae3cc27e244160bbc8a321f716acbf15747e
+size 416212
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Roof.png b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Roof.png
new file mode 100644
index 0000000..60f27f8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/maps/Roof.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0e8c888be1ac45994fa43824b10003d5e140a9fc9e998e333401ffddf13c280d
+size 107095
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/HeatAreas.import b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/HeatAreas.import
new file mode 100644
index 0000000..72ddff0
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/HeatAreas.import
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" >
+ <Group id="Group_HeatAreas" name="Group_HeatAreas" orientation="Right Handed" position="0 0 -0" rotation="-90 -0 0" rotationorder="XYZr" scale="100 100 100" >
+ <Model id="Heat_Entrance HeatAreas" name="Heat_Entrance HeatAreas" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\Heat_Entrance HeatAreas.mesh#1" >
+ <Material id="Heat_EntranceSG" name="Heat_EntranceSG" blendmode="Normal" diffuse="0.65 0.65 0.65" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_Sauna" name="HeatAreas Heat_Sauna" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_Sauna.mesh#1" >
+ <Material id="Heat_SaunaSG" name="Heat_SaunaSG" blendmode="Normal" diffuse="0.31 0.31 0.31" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_BathRoom" name="HeatAreas Heat_BathRoom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_BathRoom.mesh#1" >
+ <Material id="Heat_BathRoomSG" name="Heat_BathRoomSG" blendmode="Normal" diffuse="0.5 0.5 0.5" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_StoreRoom" name="HeatAreas Heat_StoreRoom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_StoreRoom.mesh#1" >
+ <Material id="Heat_StoreRoomSG" name="Heat_StoreRoomSG" blendmode="Normal" diffuse="0.21 0.21 0.21" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_DressRoom" name="HeatAreas Heat_DressRoom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_DressRoom.mesh#1" >
+ <Material id="Heat_DressRoomSG" name="Heat_DressRoomSG" blendmode="Normal" diffuse="0.89 0.89 0.89" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_LivingRoom" name="HeatAreas Heat_LivingRoom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_LivingRoom.mesh#1" >
+ <Material id="Heat_LivingRoomSG" name="Heat_LivingRoomSG" blendmode="Normal" diffuse="0.31 0.29 0.2" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_MasterBedroom" name="HeatAreas Heat_MasterBedroom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_MasterBedroom.mesh#1" >
+ <Material id="Heat_MasterBedroomSG" name="Heat_MasterBedroomSG" blendmode="Normal" diffuse="0.19 0.19 0.18" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_BedRoom" name="HeatAreas Heat_BedRoom" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_BedRoom.mesh#1" >
+ <Material id="Heat_BedRoomSG" name="Heat_BedRoomSG" blendmode="Normal" diffuse="0.31 0.49 0.58" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ <Model id="HeatAreas Heat_Toilet" name="HeatAreas Heat_Toilet" orientation="Right Handed" position="0 0 -0" rotation="90 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes\HeatAreas Heat_Toilet.mesh#1" >
+ <Material id="Heat_ToiletSG" name="Heat_ToiletSG" blendmode="Normal" diffuse="0.24 0.31 0.47" emissivepower="0" opacity="0" specularamount="0" specularroughness="1.76471" />
+ </Model>
+ </Group>
+ </Group>
+ </Graph>
+ <Import SrcFile="..\..\..\..\House\Vol2Exports\HeatAreas.fbx" ImageDir="Images" MeshDir="Meshes" >
+ <Mesh >
+ <Source >HeatAreas Heat_LivingRoom</Source>
+ <Dest >meshes\HeatAreas Heat_LivingRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Heat_Entrance HeatAreas</Source>
+ <Dest >meshes\Heat_Entrance HeatAreas.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_Sauna</Source>
+ <Dest >meshes\HeatAreas Heat_Sauna.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_Toilet</Source>
+ <Dest >meshes\HeatAreas Heat_Toilet.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_StoreRoom</Source>
+ <Dest >meshes\HeatAreas Heat_StoreRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_BedRoom</Source>
+ <Dest >meshes\HeatAreas Heat_BedRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_MasterBedroom</Source>
+ <Dest >meshes\HeatAreas Heat_MasterBedroom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_DressRoom</Source>
+ <Dest >meshes\HeatAreas Heat_DressRoom.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >HeatAreas Heat_BathRoom</Source>
+ <Dest >meshes\HeatAreas Heat_BathRoom.mesh</Dest>
+ </Mesh>
+ </Import>
+ </Project>
+</UIP>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BathRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BathRoom.mesh
new file mode 100644
index 0000000..df02c6f
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BathRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e18aead7ab11e9be5eb9558a7547a901ba1e058e849e7c67267cde84673c3332
+size 1072
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BedRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BedRoom.mesh
new file mode 100644
index 0000000..c1dbfb4
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_BedRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:51cdbbe7e30f4e45754c9d3341063fb2cb8b4bd219a036496ca979274516143e
+size 596
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_DressRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_DressRoom.mesh
new file mode 100644
index 0000000..d4a85f8
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_DressRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:222446510da9bcbeb6c742d25d17ad86db760439d43981aca9aa387e91ba3d51
+size 600
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_LivingRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_LivingRoom.mesh
new file mode 100644
index 0000000..99b0236
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_LivingRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5021ff6b3834d26ba635bec3a38444d2db5a9a341d9047b95870c4a3d3d83df0
+size 3064
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_MasterBedroom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_MasterBedroom.mesh
new file mode 100644
index 0000000..d20100b
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_MasterBedroom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a695743b3441e9eaa444503c5e353b7ad5ad24217ed70aa7ffc383e35533b471
+size 1080
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Sauna.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Sauna.mesh
new file mode 100644
index 0000000..e77e3e7
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Sauna.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6afa17f05c26b53bee94c92a54c32a9090d9f0f0374fa8e3d855ba55d54b8373
+size 592
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_StoreRoom.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_StoreRoom.mesh
new file mode 100644
index 0000000..4c88238
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_StoreRoom.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b7bfb1f10bb45230c58895d941adbc044dd89436d2c486bc9ba38fdb5a0c58a4
+size 600
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Toilet.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Toilet.mesh
new file mode 100644
index 0000000..aeb9ee2
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/HeatAreas Heat_Toilet.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dbcd0d0c561a1f73188a3378339e81343ce77b2c9113ce063c5e555daecd4dea
+size 596
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/Heat_Entrance HeatAreas.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/Heat_Entrance HeatAreas.mesh
new file mode 100644
index 0000000..68af64c
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/HeatAreas/meshes/Heat_Entrance HeatAreas.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f391836bea853a31f21d460242f89028a6955f9bfa7466ab06961d780bfcbb27
+size 600
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/House.import b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/House.import
new file mode 100644
index 0000000..4c87625
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/House.import
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" >
+ <Model id="Ground" name="Ground" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath="meshes\Ground.mesh#1" >
+ <Material id="Ground_0001" name="Ground" blendmode="Normal" diffuse="0.257969 0.287919 0.389518" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="House" name="House" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath="meshes\House.mesh#1" >
+ <Material id="House_0001" name="House" blendmode="Normal" diffuse="0.64 0.64 0.64" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="Windows" name="Windows" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath="meshes\Windows.mesh#1" >
+ <Material id="WindowsSG" name="WindowsSG" blendmode="Normal" diffuse="0.44 0.83 0.93" emissivepower="0" opacity="0" specularamount="0" specularroughness="0.980392" />
+ </Model>
+ <Model id="Roof" name="Roof" orientation="Right Handed" position="0 0 4.54747e-11" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath="meshes\Roof.mesh#1" >
+ <Material id="Roof_0001" name="Roof" blendmode="Normal" diffuse="0.0836838 0.0836838 0.0836838" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ </Group>
+ </Graph>
+ <Import SrcFile="..\..\..\..\House\Vol2Exports\House.fbx" ImageDir="Images" MeshDir="Meshes" >
+ <Mesh >
+ <Source >Roof</Source>
+ <Dest >meshes\Roof.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Ground</Source>
+ <Dest >meshes\Ground.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >Windows</Source>
+ <Dest >meshes\Windows.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >House</Source>
+ <Dest >meshes\House.mesh</Dest>
+ </Mesh>
+ </Import>
+ </Project>
+</UIP>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Ground.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Ground.mesh
new file mode 100644
index 0000000..36ac289
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Ground.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8b25be4c0cded582c9aa0fc06fd53e0a5d70fb448f7f6a87fdc3982b20ea5cf6
+size 692
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/House.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/House.mesh
new file mode 100644
index 0000000..2568ef3
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/House.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:080b2e1cadc82771c0e114ca75ea5340cce164d2b49f54cfaf251cb298052f01
+size 375532
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Roof.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Roof.mesh
new file mode 100644
index 0000000..59a1889
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Roof.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d464763d1ad262ee9ec37c0e7649a2c0736db39b963fc16f909ab1b8b77fe059
+size 33324
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Windows.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Windows.mesh
new file mode 100644
index 0000000..1c7cf65
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/House/meshes/Windows.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:84defa65be6e62eb0ae63a42f33eb9982a3e741d71b72a775502e368252a57df
+size 5048
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/Light/Light.import b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/Light/Light.import
new file mode 100644
index 0000000..9deb049
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/Light/Light.import
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" />
+ </Graph>
+ <Import SrcFile="..\..\..\..\House\Vol2Exports\Light.fbx" ImageDir="Images" MeshDir="Meshes" />
+ </Project>
+</UIP>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/RoomLights.import b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/RoomLights.import
new file mode 100644
index 0000000..e39b9d5
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/RoomLights.import
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" >
+ <Model id="EntranceLightmap" name="EntranceLightmap" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath=".\meshes\EntranceLightmap.mesh#1" >
+ <Material id="House" name="House" blendmode="Normal" diffuse="0.052218 0.052218 0.052218" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="BathroomLightmap" name="BathroomLightmap" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath=".\meshes\BathroomLightmap.mesh#1" >
+ <Material id="House_0001" name="House" blendmode="Normal" diffuse="0.052218 0.052218 0.052218" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="MasterbedroomLightmap" name="MasterbedroomLightmap" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath=".\meshes\MasterbedroomLightmap.mesh#1" >
+ <Material id="House_0002" name="House" blendmode="Normal" diffuse="0.052218 0.052218 0.052218" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="LivingroomLightMap" name="LivingroomLightMap" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath=".\meshes\LivingroomLightMap.mesh#1" >
+ <Material id="House_0003" name="House" blendmode="Normal" diffuse="0.052218 0.052218 0.052218" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ <Model id="BedroomLightmap" name="BedroomLightmap" orientation="Right Handed" position="0 0 -0" rotation="9.33467e-06 -0 0" rotationorder="XYZr" scale="100 100 100" sourcepath=".\meshes\BedroomLightmap.mesh#1" >
+ <Material id="House_0004" name="House" blendmode="Normal" diffuse="0.052218 0.052218 0.052218" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.60784" />
+ </Model>
+ </Group>
+ </Graph>
+ <Import SrcFile="..\..\..\..\RoomLights\RoomLights.fbx" ImageDir="Images" MeshDir="Meshes" >
+ <Mesh >
+ <Source >BedroomLightmap</Source>
+ <Dest >.\meshes\BedroomLightmap.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >EntranceLightmap</Source>
+ <Dest >.\meshes\EntranceLightmap.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >BathroomLightmap</Source>
+ <Dest >.\meshes\BathroomLightmap.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >LivingroomLightMap</Source>
+ <Dest >.\meshes\LivingroomLightMap.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >MasterbedroomLightmap</Source>
+ <Dest >.\meshes\MasterbedroomLightmap.mesh</Dest>
+ </Mesh>
+ </Import>
+ </Project>
+</UIP>
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BathroomLightmap.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BathroomLightmap.mesh
new file mode 100644
index 0000000..f850d88
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BathroomLightmap.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:645b3f16c5f782da28944cfb45251fe23dd96080ae86c0c1c5801e898eae52fc
+size 16344
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BedroomLightmap.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BedroomLightmap.mesh
new file mode 100644
index 0000000..61ce5d4
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/BedroomLightmap.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:60f5a2c3f079add7486699a9712f2eca374a5bcd054be1386393f64bc7c28009
+size 16472
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/EntranceLightmap.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/EntranceLightmap.mesh
new file mode 100644
index 0000000..13734ba
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/EntranceLightmap.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:762e6c6890b7162f0a7cb4f46d3d6f097595a2555412373460f9eb858ed38aa0
+size 12072
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/LivingroomLightMap.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/LivingroomLightMap.mesh
new file mode 100644
index 0000000..2e9aed0
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/LivingroomLightMap.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5f1727480055d9de07f96b7ee4b92fbceff3109b450c03612ab75180f83d772e
+size 108380
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/MasterbedroomLightmap.mesh b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/MasterbedroomLightmap.mesh
new file mode 100644
index 0000000..e6dfd73
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/uip/models/RoomLights/meshes/MasterbedroomLightmap.mesh
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:463612a790952c9c2ea9f6389ace48d31432db5e1bf3cd0936e034b632fba5b1
+size 18852
diff --git a/tradeshow/knx-demo/3d-Alexa-knx-demo/utils.h b/tradeshow/knx-demo/3d-Alexa-knx-demo/utils.h
new file mode 100644
index 0000000..147e8d0
--- /dev/null
+++ b/tradeshow/knx-demo/3d-Alexa-knx-demo/utils.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt 3D Studio Demos.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "demodatapoint.h"
+
+#include <QtKnx/QKnxAddress>
+#include <QtKnx/QKnxNpduFactory>
+
+QKnxTunnelFrame createRequestFrame(const QKnxAddress &address, const QKnxNpdu &npdu,
+ quint8 ctrl = 0xac, quint8 extCtrl = 0xe0)
+{
+ QKnxTunnelFrame frame(QKnxTunnelFrame::MessageCode::DataRequest);
+ frame.setControlField(QKnxControlField(ctrl));
+ frame.setExtendedControlField(QKnxExtendedControlField(extCtrl));
+ frame.setSourceAddress({ QKnxAddress::Type::Group, 0 });
+ frame.setDestinationAddress(address);
+ frame.setNpdu(npdu);
+ return frame;
+}
+
+void sendGroupValueWrite(QmlKnxTunnel &tunnel, const QKnxAddress &address,
+ const QByteArray &data, quint8 ctrl = 0xa4, quint8 extCtrl = 0xe0)
+{
+ tunnel.sendTunnelFrame(createRequestFrame(address,
+ QKnxNpduFactory::Multicast::createGroupValueWriteNpdu(data), ctrl, extCtrl));
+}
+
+void sendColorLedGroupValueWriteFrames(QmlKnxTunnel &tunnel, const DemoColorLed *const dpt)
+{
+ if (dpt) {
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 12),
+ QKnxNpduFactory::Multicast::createGroupValueWriteNpdu(dpt->redBytes())));
+
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 13),
+ QKnxNpduFactory::Multicast::createGroupValueWriteNpdu(dpt->greenBytes())));
+
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 14),
+ QKnxNpduFactory::Multicast::createGroupValueWriteNpdu(dpt->blueBytes())));
+ }
+}
+
+void initBoard(EtsDevelopmentBoard &board, QmlKnxTunnel &tunnel)
+{
+ auto npdu = QKnxNpduFactory::Multicast::createGroupValueReadNpdu();
+ for (int i = 1; i <= board.size(); ++i) {
+ if (i >= 9 && i <= 12)
+ continue; // skip red leds readings because they are not indicating the state!
+ if ((i == 7) || (i == 8) || (i == 16))
+ continue; // skip checking blinds state
+
+ if (QKnxAddress::createGroup(0, 0, 12) == board.getAddress(i)) {
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 12), npdu));
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 13), npdu));
+ tunnel.sendTunnelFrame(createRequestFrame(QKnxAddress::createGroup(0, 0, 14), npdu));
+ } else {
+ tunnel.sendTunnelFrame(createRequestFrame(board.getAddress(i), npdu, 0xa4));
+ }
+ }
+}
+
+#endif