diff --git a/README.md b/README.md
index f8e1028..4aa31b5 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,9 @@
This is a Gui for OpenZWave, intended to replace the open-zwave-control-panel eventually.
Work in Progress. Don't expect much right now :)
+
+If you are using the ozwdaemon docker image, you need to allow remote network access to the Docker Image:
+
+```docker run -it --security-opt seccomp=unconfined --device=/dev/ttyUSB0 -v /tmp/ozw:/opt/ozw/config -e MQTT_SERVER="10.100.200.102" -e USBPATH=/dev/ttyUSB0 --network host openzwave/ozwdaemon:latest```
+
+Then in the OZWAdmin gui, when opening a "Remote Connection" specify the IP address of the Host the Docker Image is running on.
diff --git a/osxmakebundle.sh b/osxmakebundle.sh
deleted file mode 100755
index e52fea9..0000000
--- a/osxmakebundle.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-if [ $# -lt 3 ]; then
- echo "Please Provide the path to the App Bundle and OZW Config Directory and QT Directories"
- exit 1
-fi
-if [ ! -f $1/Contents/Frameworks/libqt-openzwave.1.dylib ]; then
- echo "$1/Contents/Frameworks/libqt-openzwave.1.dylib doens't exist"
- exit 1
-fi
-if [ ! -f $2/manufacturer_specific.xml ]; then
- echo "$2/manufacturer_specific.xml doesn't exist"
- exit 1
-fi
-if [ ! -f $3/bin/macdeployqt ]; then
- echo "$3/bin/macdeployqt does't exist"
- exit 1
-fi
-PATH=`otool -L $1/Contents/Frameworks/libqt-openzwave.1.dylib | grep libopenzwave | awk '{print $1}'`
-/usr/bin/install_name_tool -change $PATH "@rpath/${PATH##*/}" $1/Contents/Frameworks/libqt-openzwave.1.dylib
-/bin/cp -r $2 $1/Contents/Resources/config/
-echo "To Finish Please Run '$3/bin/macdeployqt $1 -verbose=2 -always-overwrite'"
diff --git a/ozw-admin.pri b/ozw-admin.pri
new file mode 100644
index 0000000..83d3ed7
--- /dev/null
+++ b/ozw-admin.pri
@@ -0,0 +1,172 @@
+top_srcdir=$$PWD
+top_builddir=$$shadowed($$PWD)
+unix {
+ macx {
+ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
+ }
+ !macx: QMAKE_CXXFLAGS += -Wno-deprecated-copy
+}
+
+unix {
+ CONFIG-= no-pkg-config
+ CONFIG+= link_pkgconfig
+ !isEmpty(OZW_LIB_PATH) {
+ !exists($$OZW_LIB_PATH/libopenzwave.so): error("Can't find libopenzwave.so")
+ !exists($$OZW_INCLUDE_PATH/Manager.h) {
+ !exists($$OZW_LIB_PATH/cpp/src/Manager.h) {
+ error("Can't find Manager.h")
+ } else {
+ OZW_INCLUDE_PATH=$$OZW_LIB_PATH/cpp/src/
+ }
+ }
+ !exists($$OZW_DATABASE_PATH/manufacturer_specific.xml) {
+ !exists($$OZW_LIB_PATH/config/manufacturer_specific.xml) {
+ error("Can't find manufacturer_specific.xml")
+ } else {
+ OZW_DATABASE_PATH=$$absolute_path($$OZW_LIB_PATH/config/)
+ }
+ }
+ OZW_LIB_PATH=$$absolute_path($$OZW_LIB_PATH)
+ OZW_INCLUDE_PATH=$$absolute_path($$OZW_INCLUDE_PATH)
+ OZW_LIBS="-L$$OZW_LIB_PATH"
+ OZW_LIBS+="-lopenzwave"
+ OZW_DATABASE_PATH=$$absolute_path($$OZW_DATABASE_PATH)
+ message(" ")
+ message("OpenZWave Summary:")
+ message(" OpenZWave Library Path: $$OZW_LIB_PATH")
+ message(" OpenZWave Include Path: $$OZW_INCLUDE_PATH")
+ message(" OpenZWave Libs Command: $$OZW_LIBS")
+ message(" OpenZWave Database Path: $$OZW_DATABASE_PATH")
+ message(" ")
+ INCLUDEPATH+=$$OZW_INCLUDE_PATH
+ LIBS+=$$OZW_LIBS
+ } else {
+ exists( $$top_srcdir/../open-zwave/cpp/src/) {
+ message("Found OZW in $$absolute_path($$top_srcdir/../open-zwave/)")
+ OZW_LIB_PATH = "$$absolute_path($$top_srcdir/../open-zwave/)"
+ OZW_INCLUDE_PATH = $$absolute_path($$top_srcdir/../open-zwave/cpp/src/)
+ OZW_LIBS="-L$$OZW_LIB_PATH"
+ OZW_LIBS+="-lopenzwave"
+ OZW_DATABASE_PATH = $$absolute_path($$top_srcdir/../open-zwave/config/)
+ message(" ")
+ message("OpenZWave Summary:")
+ message(" OpenZWave Library Path: $$OZW_LIB_PATH")
+ message(" OpenZWave Include Path: $$OZW_INCLUDE_PATH")
+ message(" OpenZWave Libs Command: $$OZW_LIBS")
+ message(" OpenZWave Database Path: $$OZW_DATABASE_PATH")
+ message(" ")
+ INCLUDEPATH+=$$OZW_INCLUDE_PATH
+ LIBS+=$$OZW_LIBS
+ } else {
+ packagesExist("libopenzwave") {
+ PKGCONFIG += libopenzwave
+ OZW_DATABASE_PATH=$$system($$PKG_CONFIG --variable=sysconfdir libopenzwave)
+ message(" ")
+ message("OpenZWave Summary:")
+ message(" Using OpenZWave from pkg-config:")
+ message(" CXXFLAGS: $$system($$PKG_CONFIG --cflags libopenzwave)")
+ message(" LDFLAGS: $$system($$PKG_CONFIG --libs libopenzwave)")
+ message(" DATABASE: $$system($$PKG_CONFIG --variable=sysconfdir libopenzwave)")
+ message(" ")
+ } else {
+ error("Can't find OpenZWave Library and Headers");
+ }
+ }
+ }
+
+ !isEmpty(QTOZW_LIB_PATH) {
+ !exists($$QTOZW_LIB_PATH/qt-openzwave/libqt-openzwave.so): error("Can't find libqt-openzwave.so")
+ !exists($$QTOZW_INCLUDE_PATH/qt-openzwave/qtopenzwave.h) {
+ !exists($$QTOZW_LIB_PATH/qt-openzwave/include/qt-openzwave/qtopenzwave.h) {
+ error("Can't find Manager.h")
+ } else {
+ QTOZW_INCLUDE_PATH=$$QTOZW_LIB_PATH/qt-openzwave/include/
+ }
+ }
+ QTOZW_LIB_PATH=$$absolute_path($$QTOZW_LIB_PATH)
+ QTOZW_INCLUDE_PATH=$$absolute_path($$QTOZW_INCLUDE_PATH)
+ QTOZW_INCLUDE_PATH+=$$absolute_path($$QTOZW_INCLUDE_PATH/../../qt-openzwavedatabase/include/)
+ QTOZW_LIBS="-L$$absolute_path($$QTOZW_LIB_PATH/qt-openzwave/)"
+ QTOZW_LIBS+="-lqt-openzwave"
+ QTOZW_LIBS+="-L$$absolute_path($$QTOZW_LIB_PATH/qt-openzwavedatabase/)"
+ QTOZW_LIBS+="-lqt-openzwavedatabase"
+ message(" ")
+ message("QT-OpenZWave Summary:")
+ message(" QT-OpenZWave Library Path: $$QTOZW_LIB_PATH")
+ message(" QT-OpenZWave Include Path: $$QTOZW_INCLUDE_PATH")
+ message(" Qt-OpenZWave Libs Command: $$QTOZW_LIBS")
+ message(" ")
+ INCLUDEPATH+=$$QTOZW_INCLUDE_PATH
+ LIBS+=$$QTOZW_LIBS
+ } else {
+ exists($$top_srcdir/../qt-openzwave/qt-openzwave/include/qt-openzwave/qtopenzwave.h) {
+ message("Found QTOZW in $$absolute_path($$top_srcdir/../qt-openzwave/)")
+ QTOZW_LIB_PATH = "$$absolute_path($$top_srcdir/../qt-openzwave/qt-openzwave/)"
+ QTOZW_INCLUDE_PATH = $$absolute_path($$top_srcdir/../qt-openzwave/qt-openzwave/include/)
+ QTOZW_INCLUDE_PATH += $$absolute_path($$top_srcdir/../qt-openzwave/qt-openzwavedatabase/include/)
+ QTOZW_LIBS="-L$$QTOZW_LIB_PATH"
+ QTOZW_LIBS+="-lqt-openzwave"
+ QTOZW_LIBS+="-L$$absolute_path($$QTOZW_LIB_PATH/../qt-openzwavedatabase/)"
+ QTOZW_LIBS+="-lqt-openzwavedatabase"
+ message(" ")
+ message("QT-OpenZWave Summary:")
+ message(" QT-OpenZWave Library Path: $$QTOZW_LIB_PATH")
+ message(" QT-OpenZWave Include Path: $$QTOZW_INCLUDE_PATH")
+ message(" QT-OpenZWave Libs Command: $$QTOZW_LIBS")
+ message(" ")
+ INCLUDEPATH+=$$QTOZW_INCLUDE_PATH
+ LIBS+=$$QTOZW_LIBS
+ } else {
+ packagesExist("libqt-openzwave") {
+ PKGCONFIG += libqt-openzwave
+ message(" ")
+ message("QT-OpenZWave Summary:")
+ message(" Using QT-OpenZWave from pkg-config:")
+ message(" CXXFLAGS: $$system($$PKG_CONFIG --cflags libqt-openzwave)")
+ message(" LDFLAGS: $$system($$PKG_CONFIG --libs libqt-openzwave)")
+ message(" ")
+ } else {
+ error("Can't find QT-OpenZWave Library and Headers");
+ }
+ }
+ }
+
+
+}
+
+win32 {
+ CONFIG(debug, debug|release) {
+ BUILDTYPE = debug
+ } else {
+ BUILDTYPE = release
+ }
+ message(Checking for $$BUILDTYPE build of OZW)
+ exists( $$top_srcdir/../open-zwave/cpp/src/) {
+ message("Found OZW in $$absolute_path($$top_srcdir/../open-zwave/cpp/src)")
+ INCLUDEPATH += $$absolute_path($$top_srcdir/../open-zwave/cpp/src/)/
+ INCLUDEPATH += $$absolute_path($$top_srcdir/../qt-openzwave/qt-openzwave/include/)
+ INCLUDEPATH += $$absolute_path($$top_srcdir/../qt-openzwave/qt-openzwavedatabase/include/)
+ equals(BUILDTYPE, "release") {
+ exists( $$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/ReleaseDLL/OpenZWave.dll ) ) {
+ LIBS += -L$$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/ReleaseDLL) -lopenzwave
+ OZW_LIB_PATH = $$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/ReleaseDLL)
+ } else {
+ error("Can't find a copy of OpenZWave.dll in the ReleaseDLL Directory");
+ }
+ } else {
+ equals(BUILDTYPE, "debug") {
+ exists ( $$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/DebugDLL/OpenZWaved.dll )) {
+ LIBS += -L$$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/DebugDLL) -lOpenZWaved
+ OZW_LIB_PATH = $$absolute_path($$top_srcdir/../open-zwave/cpp/build/windows/vs2010/ReleaseDLL)
+ } else {
+ error("Can't find a copy of OpenZWaved.dll in the DebugDLL Directory");
+ }
+ }
+ }
+ isEmpty(OZW_LIB_PATH) {
+ error("Can't find a copy of OpenZWave with the right builds");
+ }
+ } else {
+ error("Can't Find a copy of OpenZwave")
+ }
+}
diff --git a/ozwadmin-main/mainwindow.cpp b/ozwadmin-main/mainwindow.cpp
index 3b9945c..d8fdfbc 100644
--- a/ozwadmin-main/mainwindow.cpp
+++ b/ozwadmin-main/mainwindow.cpp
@@ -55,6 +55,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionOpen_Log_Window, SIGNAL(triggered()), this, SLOT(openLogWindow()));
connect(ui->actionOpen_Serial_Port, SIGNAL(triggered()), this, SLOT(OpenSerialPort()));
+ connect(ui->actionOpen_Remote, SIGNAL(triggered()), this, SLOT(OpenRemote()));
+ connect(ui->action_Close, SIGNAL(triggered()), this, SLOT(CloseConnection()));
connect(ui->actionDevice_Database, SIGNAL(triggered()), this, SLOT(OpenDeviceDB()));
connect(ui->md_helpwindow, &QPushButton::clicked, this, &MainWindow::openMetaDataWindow);
connect(ui->action_Configuration, SIGNAL(triggered()), this, SLOT(openConfigWindow()));
@@ -199,7 +201,12 @@ MainWindow::MainWindow(QWidget *parent) :
qDebug() << directory.absoluteFilePath();
if (directory.exists()) {
#ifndef _WIN32
+ QStringList dirs;
+ dirs << directory.absoluteFilePath().append("/");
+ initConfigDatabase(dirs);
+#if 0
copyConfigDatabase(directory.absoluteFilePath().append("/"));
+#endif
#endif
m_configpath.setPath(directory.absoluteFilePath().append("/config/"));
m_userpath.setPath(directory.absoluteFilePath().append("/config/"));
@@ -320,10 +327,36 @@ void MainWindow::QTOZW_Ready() {
this->m_statTimer.start(1000);
}
+void MainWindow::OpenRemote() {
+ bool ok;
+
+ QString text = QInputDialog::getText(this, tr("Enter Remote Host"),
+ tr("Hostname/IP Address:"), QLineEdit::Normal,
+ "localhost", &ok);
+ if (!ok)
+ return;
+
+ QUrl server;
+ server.setHost(text);
+ server.setPort(1983);
+ server.setScheme("tcp");
+ qDebug() << "Connecting to " << server;
+ this->m_qtozwmanager->initilizeReplica(server);
+
+}
+void MainWindow::CloseConnection() {
+
+}
+
void MainWindow::OpenSerialPort() {
bool ok;
+
+ QMessageBox::warning(this, tr("OZW-Admin"),
+ tr("This is Work In Progress!"),
+ QMessageBox::Ok);
+
QString text = QInputDialog::getText(this, tr("Select Serial Port"),
tr("Serial Port:"), QLineEdit::Normal,
this->m_serialport, &ok);
diff --git a/ozwadmin-main/mainwindow.h b/ozwadmin-main/mainwindow.h
index 88f4016..4733eac 100644
--- a/ozwadmin-main/mainwindow.h
+++ b/ozwadmin-main/mainwindow.h
@@ -42,6 +42,8 @@ public:
Q_PROPERTY(QString SerialPort MEMBER m_serialport)
public slots:
void OpenSerialPort();
+ void OpenRemote();
+ void CloseConnection();
void resizeColumns();
void NodeSelected(QModelIndex,QModelIndex);
void openLogWindow();
diff --git a/ozwadmin-main/mainwindow.ui b/ozwadmin-main/mainwindow.ui
index 222005a..bf97c32 100644
--- a/ozwadmin-main/mainwindow.ui
+++ b/ozwadmin-main/mainwindow.ui
@@ -907,7 +907,7 @@
0
0
- 98
+ 85
71
@@ -1086,6 +1086,8 @@
false
+
+
@@ -1120,6 +1122,22 @@
&Device Database
+
+
+ Open &Remote
+
+
+ Open Remote
+
+
+
+
+ &Close
+
+
+ Close Local or Remote Connection
+
+
diff --git a/ozwadmin-main/ozwadmin-main.pro b/ozwadmin-main/ozwadmin-main.pro
index 6c9edc7..8c02adf 100644
--- a/ozwadmin-main/ozwadmin-main.pro
+++ b/ozwadmin-main/ozwadmin-main.pro
@@ -5,7 +5,7 @@
#-------------------------------------------------
QT += core gui widgets xml remoteobjects websockets svg
-CONFIG += silent
+#CONFIG += silent
TARGET = ../ozwadmin
TEMPLATE = app
@@ -31,18 +31,18 @@ FORMS += mainwindow.ui \
RESOURCES += \
ozwadmin-main.qrc \
+include(../ozw-admin.pri)
-
-#LIBS += ../devicedb-lib/libdevicedb-lib.a ../ozwadmin-widgets/libozwadmin-widgets.a
unix {
+ target.path = /usr/local/bin
+ INSTALLS += target
LIBS += -L../devicedb-lib/ -ldevicedb-lib -L../ozwadmin-widgets/ -lozwadmin-widgets
- LIBS += -L../../qt-openzwave/qt-openzwave/ -lqt-openzwave -L../../qt-openzwave/qt-openzwavedatabase -lqt-openzwavedatabase
}
windows {
CONFIG(debug, debug|release) {
LIBS += -L..\devicedb-lib\debug\ -L..\ozwadmin-widgets\debug\ -L..\..\qt-openzwave\qt-openzwave\debug\
} else {
- LIBS += -L..\devicedb-lib\release\ -L..\ozwadmin-widgets\release\ -L..\..\qt-openzwave\qt-openzwave\release\
+ LIBS += -L..\devicedb-lib\release\ -L..\ozwadmin-widgets\release\ -L..\..\qt-openzwave\qt-openzwave\release\
}
LIBS += -ldevicedb-lib -lozwadmin-widgets -lqt-openzwave1
message($$LIBS)
@@ -51,14 +51,15 @@ windows {
INCLUDEPATH += ../devicedb-lib ../ozwadmin-widgets
-INCLUDEPATH += ../../qt-openzwave/qt-openzwave/include/ ../../qt-openzwave/qt-openzwavedatabase/include/
-
macx: {
LIBS += -framework IOKit -framework CoreFoundation
- BUNDLE.files = ../../qt-openzwave/qt-openzwave/libqt-openzwave.1.dylib ../../open-zwave/libopenzwave-1.6.dylib ../../qt-openzwave/qt-openzwavedatabase/libqt-openzwavedatabase.1.dylib
+ BUNDLE.files = $$OZW_LIB_PATH/libopenzwave-1.6.dylib $$QTOZW_LIB_PATH/libqt-openzwave.1.dylib $$QTOZW_LIB_PATH/../qt-openzwavedatabase/libqt-openzwavedatabase.1.dylib
BUNDLE.path = Contents/Frameworks/
QMAKE_BUNDLE_DATA += BUNDLE
+ MakeBundle.commands = $$[QT_HOST_BINS]/macdeployqt ../ozwadmin.app && $$top_srcdir/scripts/macdeployqtfix.py ../ozwadmin.app/Contents/MacOS/ozwadmin $$[QT_INSTALL_PREFIX]
+ QMAKE_EXTRA_TARGETS += MakeBundle
+ QMAKE_POST_LINK += $$MakeBundle.commands
ICON = res/ozw_logo.icns
}
diff --git a/ozwadmin-widgets/ozwadmin-widgets.pro b/ozwadmin-widgets/ozwadmin-widgets.pro
index 4899d2e..afe396f 100644
--- a/ozwadmin-widgets/ozwadmin-widgets.pro
+++ b/ozwadmin-widgets/ozwadmin-widgets.pro
@@ -44,7 +44,9 @@ FORMS += HelpEditorDlg.ui \
bitsetwidget.ui \
nodeflagswidget.ui
-INCLUDEPATH += ../devicedb-lib ../ozwadmin-main ../../qt-openzwave/qt-openzwave/include/
+include(../ozw-admin.pri)
+
+INCLUDEPATH += ../devicedb-lib ../ozwadmin-main
macx: {
diff --git a/qt-openzwave.pri b/qt-openzwave.pri
deleted file mode 100644
index b303d71..0000000
--- a/qt-openzwave.pri
+++ /dev/null
@@ -1,2 +0,0 @@
-top_srcdir=$$PWD
-top_builddir=$$shadowed($$PWD)
diff --git a/scripts/Dockerfile b/scripts/Dockerfile
new file mode 100644
index 0000000..829b075
--- /dev/null
+++ b/scripts/Dockerfile
@@ -0,0 +1,11 @@
+#DockerFile to build a image capabile of Building AppImages. See build.sh for details
+FROM ubuntu:xenial
+WORKDIR /opt
+
+RUN apt update && apt-get install -y software-properties-common && add-apt-repository ppa:beineri/opt-qt-5.12.6-xenial && \
+apt update && apt-get install -y qt512-meta-minimal qt512remoteobjects rapidjson-dev git g++ cmake make pkgconf bash python wget joe mc libunwind-dev libcurl4-openssl-dev qt512svg qt512websockets mesa-common-dev libgl1-mesa-dev fuse appstream && \
+wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage && \
+wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage && \
+chmod +x linuxdeploy*.AppImage
+VOLUME /opt/buildfiles
+ENTRYPOINT /opt/buildfiles/build.sh
\ No newline at end of file
diff --git a/scripts/build.sh b/scripts/build.sh
new file mode 100755
index 0000000..4906acd
--- /dev/null
+++ b/scripts/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#Build File for Docker Image.
+#Run docker in this directory with: docker run -it --rm --device /dev/fuse --privileged -v`pwd`:/opt/buildfiles -e DOCKERUSERID=`id -u` -e DOCKERGROUPID=`id -g`
+cd /opt
+git clone https://github.com/OpenZWave/open-zwave.git && cd open-zwave && make -j4 && make install
+cd /opt
+git clone https://github.com/OpenZWave/qt-openzwave.git && cd qt-openzwave && /opt/qt512/bin/qmake -r && make -j4 && make install
+cd /opt
+git clone https://github.com/OpenZWave/ozw-admin.git && cd ozw-admin && git checkout buildfixes && /opt/qt512/bin/qmake -r && make -j4 && make install
+cd /opt
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib64
+export QMAKE=/opt/qt512/bin/qmake
+export VERSION=0.1
+cd ozw-admin && ../linuxdeploy-x86_64.AppImage --appdir AppDir -e ozwadmin --plugin qt --output appimage -d scripts/ozwadmin.desktop -i scripts/ozwadmin.png
+cp /opt/ozw-admin/OZWAdmin-*.AppImage /opt/buildfiles/
+chown $DOCKERUSERID:$DOCKERGROUPID /opt/buildfiles/OZWAdmin-*.AppImage
diff --git a/scripts/dmgbuild.py b/scripts/dmgbuild.py
new file mode 100644
index 0000000..d1af1ca
--- /dev/null
+++ b/scripts/dmgbuild.py
@@ -0,0 +1,205 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import biplist
+import os.path
+
+#
+# Example settings file for dmgbuild
+#
+
+# Use like this: dmgbuild -s settings.py "Test Volume" test.dmg
+
+# You can actually use this file for your own application (not just TextEdit)
+# by doing e.g.
+#
+# dmgbuild -s settings.py -D app=/path/to/My.app "My Application" MyApp.dmg
+
+# .. Useful stuff ..............................................................
+
+application = defines.get('app', '../ozwadmin.app')
+appname = os.path.basename(application)
+
+def icon_from_app(app_path):
+ plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
+ plist = biplist.readPlist(plist_path)
+ icon_name = plist['CFBundleIconFile']
+ icon_root,icon_ext = os.path.splitext(icon_name)
+ if not icon_ext:
+ icon_ext = '.icns'
+ icon_name = icon_root + icon_ext
+ return os.path.join(app_path, 'Contents', 'Resources', icon_name)
+
+# .. Basics ....................................................................
+
+# Uncomment to override the output filename
+# filename = 'test.dmg'
+
+# Uncomment to override the output volume name
+# volume_name = 'Test'
+
+# Volume format (see hdiutil create -help)
+format = defines.get('format', 'UDBZ')
+
+# Compression level (if relevant)
+# compression_level = 9
+
+# Volume size
+size = defines.get('size', None)
+
+# Files to include
+files = [ application ]
+
+# Symlinks to create
+symlinks = { 'Applications': '/Applications' }
+
+# Volume icon
+#
+# You can either define icon, in which case that icon file will be copied to the
+# image, *or* you can define badge_icon, in which case the icon file you specify
+# will be used to badge the system's Removable Disk icon. Badge icons require
+# pyobjc-framework-Quartz.
+#
+#icon = '/path/to/icon.icns'
+badge_icon = icon_from_app(application)
+
+# Where to put the icons
+icon_locations = {
+ appname: (140, 120),
+ 'Applications': (500, 120)
+ }
+
+# .. Window configuration ......................................................
+
+# Background
+#
+# This is a STRING containing any of the following:
+#
+# #3344ff - web-style RGB color
+# #34f - web-style RGB color, short form (#34f == #3344ff)
+# rgb(1,0,0) - RGB color, each value is between 0 and 1
+# hsl(120,1,.5) - HSL (hue saturation lightness) color
+# hwb(300,0,0) - HWB (hue whiteness blackness) color
+# cmyk(0,1,0,0) - CMYK color
+# goldenrod - X11/SVG named color
+# builtin-arrow - A simple built-in background with a blue arrow
+# /foo/bar/baz.png - The path to an image file
+#
+# The hue component in hsl() and hwb() may include a unit; it defaults to
+# degrees ('deg'), but also supports radians ('rad') and gradians ('grad'
+# or 'gon').
+#
+# Other color components may be expressed either in the range 0 to 1, or
+# as percentages (e.g. 60% is equivalent to 0.6).
+background = 'builtin-arrow'
+
+show_status_bar = False
+show_tab_view = False
+show_toolbar = False
+show_pathbar = False
+show_sidebar = False
+sidebar_width = 180
+
+# Window position in ((x, y), (w, h)) format
+window_rect = ((100, 100), (640, 280))
+
+# Select the default view; must be one of
+#
+# 'icon-view'
+# 'list-view'
+# 'column-view'
+# 'coverflow'
+#
+default_view = 'icon-view'
+
+# General view configuration
+show_icon_preview = False
+
+# Set these to True to force inclusion of icon/list view settings (otherwise
+# we only include settings for the default view)
+include_icon_view_settings = 'auto'
+include_list_view_settings = 'auto'
+
+# .. Icon view configuration ...................................................
+
+arrange_by = None
+grid_offset = (0, 0)
+grid_spacing = 100
+scroll_position = (0, 0)
+label_pos = 'bottom' # or 'right'
+text_size = 16
+icon_size = 128
+
+# .. List view configuration ...................................................
+
+# Column names are as follows:
+#
+# name
+# date-modified
+# date-created
+# date-added
+# date-last-opened
+# size
+# kind
+# label
+# version
+# comments
+#
+list_icon_size = 16
+list_text_size = 12
+list_scroll_position = (0, 0)
+list_sort_by = 'name'
+list_use_relative_dates = True
+list_calculate_all_sizes = False,
+list_columns = ('name', 'date-modified', 'size', 'kind', 'date-added')
+list_column_widths = {
+ 'name': 300,
+ 'date-modified': 181,
+ 'date-created': 181,
+ 'date-added': 181,
+ 'date-last-opened': 181,
+ 'size': 97,
+ 'kind': 115,
+ 'label': 100,
+ 'version': 75,
+ 'comments': 300,
+ }
+list_column_sort_directions = {
+ 'name': 'ascending',
+ 'date-modified': 'descending',
+ 'date-created': 'descending',
+ 'date-added': 'descending',
+ 'date-last-opened': 'descending',
+ 'size': 'descending',
+ 'kind': 'ascending',
+ 'label': 'ascending',
+ 'version': 'ascending',
+ 'comments': 'ascending',
+ }
+
+# .. License configuration .....................................................
+
+# Text in the license configuration is stored in the resources, which means
+# it gets stored in a legacy Mac encoding according to the language. dmgbuild
+# will *try* to convert Unicode strings to the appropriate encoding, *but*
+# you should be aware that Python doesn't support all of the necessary encodings;
+# in many cases you will need to encode the text yourself and use byte strings
+# instead here.
+
+# Recognized language names are:
+#
+# af_ZA, ar, be_BY, bg_BG, bn, bo, br, ca_ES, cs_CZ, cy, da_DK, de_AT, de_CH,
+# de_DE, dz_BT, el_CY, el_GR, en_AU, en_CA, en_GB, en_IE, en_SG, en_US, eo,
+# es_419, es_ES, et_EE, fa_IR, fi_FI, fo_FO, fr_001, fr_BE, fr_CA, fr_CH,
+# fr_FR, ga-Latg_IE, ga_IE, gd, grc, gu_IN, gv, he_IL, hi_IN, hr_HR, hu_HU,
+# hy_AM, is_IS, it_CH, it_IT, iu_CA, ja_JP, ka_GE, kl, ko_KR, lt_LT, lv_LV,
+# mk_MK, mr_IN, mt_MT, nb_NO, ne_NP, nl_BE, nl_NL, nn_NO, pa, pl_PL, pt_BR,
+# pt_PT, ro_RO, ru_RU, se, sk_SK, sl_SI, sr_RS, sv_SE, th_TH, to_TO, tr_TR,
+# uk_UA, ur_IN, ur_PK, uz_UZ, vi_VN, zh_CN, zh_TW
+
+license = {
+ 'default-language': 'en_US',
+ 'licenses': {
+ 'en_US': './LICENSE'
+ },
+ }
diff --git a/scripts/macdeployqtfix.py b/scripts/macdeployqtfix.py
new file mode 100755
index 0000000..29d3810
--- /dev/null
+++ b/scripts/macdeployqtfix.py
@@ -0,0 +1,395 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+finish the job started by macdeployqtfix
+"""
+
+from subprocess import Popen, PIPE
+from string import Template
+import os
+import sys
+import logging
+import argparse
+import re
+from collections import namedtuple
+
+
+QTLIB_NAME_REGEX = r'^(?:@executable_path)?/.*/(Qt[a-zA-Z]*).framework/(?:Versions/\d/)?\1$'
+QTLIB_NORMALIZED = r'$prefix/Frameworks/$qtlib.framework/Versions/$qtversion/$qtlib'
+
+QTPLUGIN_NAME_REGEX = r'^(?:@executable_path)?/.*/[pP]lug[iI]ns/(.*)/(.*).dylib$'
+QTPLUGIN_NORMALIZED = r'$prefix/PlugIns/$plugintype/$pluginname.dylib'
+
+#BREWLIB_REGEX = r'^//usr/local/.*//(.*)'
+BREWLIB_REGEX =r'.*(lib.*openzwave.*dylib)'
+BREWLIB_NORMALIZED = r'$prefix/Frameworks/$brewlib'
+
+
+class GlobalConfig(object):
+ logger = None
+ qtpath = None
+ exepath = None
+
+
+def run_and_get_output(popen_args):
+ """Run process and get all output"""
+ process_output = namedtuple('ProcessOutput', ['stdout', 'stderr', 'retcode'])
+ try:
+ GlobalConfig.logger.debug('run_and_get_output({0})'.format(repr(popen_args)))
+
+ proc = Popen(popen_args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = proc.communicate(b'')
+ proc_out = process_output(stdout, stderr, proc.returncode)
+
+ GlobalConfig.logger.debug('\tprocess_output: {0}'.format(proc_out))
+ return proc_out
+ except Exception as exc:
+ GlobalConfig.logger.error('\texception: {0}'.format(exc))
+ return process_output('', exc.message, -1)
+
+
+def get_dependencies(filename):
+ """
+ input: filename must be an absolute path
+ Should call `otool` and returns the list of dependencies, unsorted,
+ unmodified, just the raw list so then we could eventually re-use in other
+ more specialized functions
+ """
+ GlobalConfig.logger.debug('get_dependencies({0})'.format(filename))
+ popen_args = ['otool', '-L', filename]
+ proc_out = run_and_get_output(popen_args)
+ deps = []
+ if proc_out.retcode == 0:
+ # some string splitting
+ deps = [s.strip().split(' ')[0] for s in proc_out.stdout.splitlines()[1:] if s]
+ # prevent infinite recursion when a binary depends on itself (seen with QtWidgets)...
+ deps = [s for s in deps if os.path.basename(filename) not in s]
+ return deps
+
+
+def is_qt_plugin(filename):
+ """
+ Checks if a given file is a qt plugin.
+ Accepts absolute path as well as path containing @executable_path
+ """
+ qtlib_name_rgx = re.compile(QTPLUGIN_NAME_REGEX)
+ return qtlib_name_rgx.match(filename) is not None
+
+
+def is_qt_lib(filename):
+ """
+ Checks if a given file is a qt library.
+ Accepts absolute path as well as path containing @executable_path
+ """
+ qtlib_name_rgx = re.compile(QTLIB_NAME_REGEX)
+ return qtlib_name_rgx.match(filename) is not None
+
+
+def is_brew_lib(filename):
+ """
+ Checks if a given file is a brew library
+ Accepts absolute path as well as path containing @executable_path
+ """
+ qtlib_name_rgx = re.compile(BREWLIB_REGEX)
+ return qtlib_name_rgx.match(filename) is not None
+
+
+def normalize_qtplugin_name(filename):
+ """
+ input: a path to a qt plugin, as returned by otool, that can have this form :
+ - an absolute path /../plugins/PLUGINTYPE/PLUGINNAME.dylib
+ - @executable_path/../plugins/PLUGINTYPE/PLUGINNAME.dylib
+ output:
+ a tuple (qtlib, abspath, rpath) where:
+ - qtname is the name of the plugin (libqcocoa.dylib, etc.)
+ - abspath is the absolute path of the qt lib inside the app bundle of exepath
+ - relpath is the correct rpath to a qt lib inside the app bundle
+ """
+
+ GlobalConfig.logger.debug('normalize_plugin_name({0})'.format(filename))
+
+ qtplugin_name_rgx = re.compile(QTPLUGIN_NAME_REGEX)
+ rgxret = qtplugin_name_rgx.match(filename)
+ if not rgxret:
+ msg = 'couldn\'t normalize a non-qt plugin filename: {0}'.format(filename)
+ GlobalConfig.logger.critical(msg)
+ raise Exception(msg)
+
+ # qtplugin normalization settings
+ qtplugintype = rgxret.groups()[0]
+ qtpluginname = rgxret.groups()[1]
+
+ templ = Template(QTPLUGIN_NORMALIZED)
+
+ # from qtlib, forge 2 path :
+ # - absolute path of qt lib in bundle,
+ abspath = os.path.normpath(templ.safe_substitute(
+ prefix=os.path.dirname(GlobalConfig.exepath) + '/..',
+ plugintype=qtplugintype,
+ pluginname=qtpluginname))
+
+ # - and rpath containing @executable_path, relative to exepath
+ rpath = templ.safe_substitute(
+ prefix='@executable_path/..',
+ plugintype=qtplugintype,
+ pluginname=qtpluginname)
+
+ GlobalConfig.logger.debug('\treturns({0})'.format((qtpluginname, abspath, rpath)))
+ return qtpluginname, abspath, rpath
+
+
+def normalize_qtlib_name(filename):
+ """
+ input: a path to a qt library, as returned by otool, that can have this form :
+ - an absolute path /lib/xxx/yyy
+ - @executable_path/../Frameworks/QtSerialPort.framework/Versions/5/QtSerialPort
+ output:
+ a tuple (qtlib, abspath, rpath) where:
+ - qtlib is the name of the qtlib (QtCore, QtWidgets, etc.)
+ - abspath is the absolute path of the qt lib inside the app bundle of exepath
+ - relpath is the correct rpath to a qt lib inside the app bundle
+ """
+ GlobalConfig.logger.debug('normalize_qtlib_name({0})'.format(filename))
+
+ qtlib_name_rgx = re.compile(QTLIB_NAME_REGEX)
+ rgxret = qtlib_name_rgx.match(filename)
+ if not rgxret:
+ msg = 'couldn\'t normalize a non-qt lib filename: {0}'.format(filename)
+ GlobalConfig.logger.critical(msg)
+ raise Exception(msg)
+
+ # qtlib normalization settings
+ qtlib = rgxret.groups()[0]
+ qtversion = 5
+
+ templ = Template(QTLIB_NORMALIZED)
+
+ # from qtlib, forge 2 path :
+ # - absolute path of qt lib in bundle,
+ abspath = os.path.normpath(templ.safe_substitute(
+ prefix=os.path.dirname(GlobalConfig.exepath) + '/..',
+ qtlib=qtlib,
+ qtversion=qtversion))
+
+ # - and rpath containing @executable_path, relative to exepath
+ rpath = templ.safe_substitute(
+ prefix='@executable_path/..',
+ qtlib=qtlib,
+ qtversion=qtversion)
+
+ GlobalConfig.logger.debug('\treturns({0})'.format((qtlib, abspath, rpath)))
+ return qtlib, abspath, rpath
+
+
+def normalize_brew_name(filename):
+ """
+ input: a path to a brew library, as returned by otool, that can have this form :
+ - an absolute path /usr/local/lib/yyy
+ output:
+ a tuple (brewlib, abspath, rpath) where:
+ - brewlib is the name of the brew lib
+ - abspath is the absolute path of the qt lib inside the app bundle of exepath
+ - relpath is the correct rpath to a qt lib inside the app bundle
+ """
+ GlobalConfig.logger.debug('normalize_brew_name({0})'.format(filename))
+
+ brewlib_name_rgx = re.compile(BREWLIB_REGEX)
+ rgxret = brewlib_name_rgx.match(filename)
+ if not rgxret:
+ msg = 'couldn\'t normalize a brew lib filename: {0}'.format(filename)
+ GlobalConfig.logger.critical(msg)
+ raise Exception(msg)
+
+ # brewlib normalization settings
+ brewlib = rgxret.groups()[0]
+ templ = Template(BREWLIB_NORMALIZED)
+
+ # from brewlib, forge 2 path :
+ # - absolute path of qt lib in bundle,
+ abspath = os.path.normpath(templ.safe_substitute(
+ prefix=os.path.dirname(GlobalConfig.exepath) + '/..',
+ brewlib=brewlib))
+
+ # - and rpath containing @executable_path, relative to exepath
+ rpath = templ.safe_substitute(
+ prefix='@executable_path/..',
+ brewlib=brewlib)
+
+ GlobalConfig.logger.debug('\treturns({0})'.format((brewlib, abspath, rpath)))
+ return brewlib, abspath, rpath
+
+
+def fix_dependency(binary, dep):
+ """
+ fix 'dep' dependency of 'binary'. 'dep' is a qt library
+ """
+ if is_qt_lib(dep):
+ qtname, dep_abspath, dep_rpath = normalize_qtlib_name(dep)
+ elif is_qt_plugin(dep):
+ qtname, dep_abspath, dep_rpath = normalize_qtplugin_name(dep)
+ elif is_brew_lib(dep):
+ qtname, dep_abspath, dep_rpath = normalize_brew_name(dep)
+ else:
+ return True
+
+ dep_ok = True
+ # check that rpath of 'dep' inside binary has been correctly set
+ # (ie: relative to exepath using '@executable_path' syntax)
+ if dep != dep_rpath:
+ # dep rpath is not ok
+ GlobalConfig.logger.info('changing rpath \'{0}\' in binary {1}'.format(dep, binary))
+
+ # call install_name_tool -change on binary
+ popen_args = ['install_name_tool', '-change', dep, dep_rpath, binary]
+ proc_out = run_and_get_output(popen_args)
+ if proc_out.retcode != 0:
+ GlobalConfig.logger.error(proc_out.stderr)
+ dep_ok = False
+ else:
+ # call install_name_tool -id on binary
+ popen_args = ['install_name_tool', '-id', dep_rpath, binary]
+ proc_out = run_and_get_output(popen_args)
+ if proc_out.retcode != 0:
+ GlobalConfig.logger.error(proc_out.stderr)
+ dep_ok = False
+
+ # now ensure that 'dep' exists at the specified path, relative to bundle
+ if False and dep_ok and not os.path.exists(dep_abspath):
+
+ # ensure destination directory exists
+ GlobalConfig.logger.info('ensuring directory \'{0}\' exists: {0}'.
+ format(os.path.dirname(dep_abspath)))
+ popen_args = ['mkdir', '-p', os.path.dirname(dep_abspath)]
+ proc_out = run_and_get_output(popen_args)
+ if proc_out.retcode != 0:
+ GlobalConfig.logger.info(proc_out.stderr)
+ dep_ok = False
+ else:
+ # copy missing dependency into bundle
+ qtnamesrc = os.path.join(GlobalConfig.qtpath, 'lib', '{0}.framework'.
+ format(qtname), qtname)
+ GlobalConfig.logger.info('copying missing dependency in bundle: {0}'.
+ format(qtname))
+ popen_args = ['cp', qtnamesrc, dep_abspath]
+ proc_out = run_and_get_output(popen_args)
+ if proc_out.retcode != 0:
+ GlobalConfig.logger.info(proc_out.stderr)
+ dep_ok = False
+ else:
+ # ensure permissions are correct if we ever have to change its rpath
+ GlobalConfig.logger.info('ensuring 755 perm to {0}'.format(dep_abspath))
+ popen_args = ['chmod', '755', dep_abspath]
+ proc_out = run_and_get_output(popen_args)
+ if proc_out.retcode != 0:
+ GlobalConfig.logger.info(proc_out.stderr)
+ dep_ok = False
+ else:
+ GlobalConfig.logger.debug('{0} is at correct location in bundle'.format(qtname))
+
+ if dep_ok:
+ return fix_binary(dep_abspath)
+ return False
+
+
+def fix_binary(binary):
+ """
+ input:
+ binary: relative or absolute path (no @executable_path syntax)
+ process:
+ - first fix the rpath for the qt libs on which 'binary' depend
+ - copy into the bundle of exepath the eventual libraries that are missing
+ - (create the soft links) needed ?
+ - do the same for all qt dependencies of binary (recursive)
+ """
+ GlobalConfig.logger.debug('fix_binary({0})'.format(binary))
+
+ # loop on 'binary' dependencies
+ for dep in get_dependencies(binary):
+ if not fix_dependency(binary, dep):
+ GlobalConfig.logger.error('quitting early: couldn\'t fix dependency {0} of {1}'.format(dep, binary))
+ return False
+ return True
+
+
+def fix_main_binaries():
+ """
+ list the main binaries of the app bundle and fix them
+ """
+ # deduce bundle path
+ bundlepath = os.path.sep.join(GlobalConfig.exepath.split(os.path.sep)[0:-3])
+
+ # fix main binary
+ GlobalConfig.logger.info('fixing executable \'{0}\''.format(GlobalConfig.exepath))
+ if fix_binary(GlobalConfig.exepath):
+ GlobalConfig.logger.info('fixing plugins')
+ for root, dummy, files in os.walk(bundlepath):
+ for name in [f for f in files if os.path.splitext(f)[1] == '.dylib']:
+ GlobalConfig.logger.info('fixing plugin {0}'.format(name))
+ if not fix_binary(os.path.join(root, name)):
+ return False
+ return True
+
+
+def main():
+ descr = """finish the job started by macdeployqt!
+ - find dependencies/rpaths with otool
+ - copy missed dependencies with cp and mkdir
+ - fix missed rpaths with install_name_tool
+
+ exit codes:
+ - 0 : success
+ - 1 : error
+ """
+
+ parser = argparse.ArgumentParser(description=descr,
+ formatter_class=argparse.RawTextHelpFormatter)
+ parser.add_argument('exepath',
+ help='path to the binary depending on Qt')
+ parser.add_argument('qtpath',
+ help='path of Qt libraries used to build the Qt application')
+ parser.add_argument('-q', '--quiet', action='store_true', default=False,
+ help='do not create log on standard output')
+ parser.add_argument('-nl', '--no-log-file', action='store_true', default=False,
+ help='do not create log file \'./macdeployqtfix.log\'')
+ parser.add_argument('-v', '--verbose', action='store_true', default=False,
+ help='produce more log messages(debug log)')
+ args = parser.parse_args()
+
+ # globals
+ GlobalConfig.qtpath = os.path.normpath(args.qtpath)
+ GlobalConfig.exepath = args.exepath
+ GlobalConfig.logger = logging.getLogger()
+
+ # configure logging
+ ###################
+
+ # create formatter
+ formatter = logging.Formatter('%(levelname)s | %(message)s')
+ # create console GlobalConfig.logger
+ if not args.quiet:
+ chdlr = logging.StreamHandler(sys.stdout)
+ chdlr.setFormatter(formatter)
+ GlobalConfig.logger.addHandler(chdlr)
+
+ # create file GlobalConfig.logger
+ if not args.no_log_file:
+ fhdlr = logging.FileHandler('./macdeployqtfix.log', mode='w')
+ fhdlr.setFormatter(formatter)
+ GlobalConfig.logger.addHandler(fhdlr)
+
+ if args.no_log_file and args.quiet:
+ GlobalConfig.logger.addHandler(logging.NullHandler())
+ else:
+ GlobalConfig.logger.setLevel(logging.DEBUG if args.verbose else logging.INFO)
+
+ if fix_main_binaries():
+ GlobalConfig.logger.info('macdeployqtfix terminated with success')
+ ret = 0
+ else:
+ GlobalConfig.logger.error('macdeployqtfix terminated with error')
+ ret = 1
+ sys.exit(ret)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/ozwadmin.desktop b/scripts/ozwadmin.desktop
new file mode 100644
index 0000000..8e70a72
--- /dev/null
+++ b/scripts/ozwadmin.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=OZWAdmin
+Comment=OpenZWave Administration Gui
+Exec=ozwadmin
+Type=Application
+Icon=ozwadmin
+Categories=System;
+MimeType=application/x-iso9660-appimage;
\ No newline at end of file
diff --git a/scripts/ozwadmin.png b/scripts/ozwadmin.png
new file mode 100644
index 0000000..c5c5450
Binary files /dev/null and b/scripts/ozwadmin.png differ
diff --git a/scripts/win32build.bat b/scripts/win32build.bat
index 9a9fd89..3049fb1 100644
--- a/scripts/win32build.bat
+++ b/scripts/win32build.bat
@@ -1,6 +1,7 @@
@echo off
cd ..\open-zwave
msbuild /p:Configuration=ReleaseDLL /p:Platform=Win32 cpp\build\windows\vs2010\OpenZWave.sln
+msbuild /p:Configuration=DebugDLL /p:Platform=Win32 cpp\build\windows\vs2010\OpenZWave.sln
cd ..\qt-openzwave
qmake -r -tp vc
msbuild /p:Configuration=Release /p:Platform=Win32 qt-openzwave.sln