Quellcode durchsuchen

Änderungen Mqtt-Parameter, u. a.

Rind vor 3 Jahren
Ursprung
Commit
0b17ca12ab

+ 4 - 4
_OEM_.cfg

@@ -134,10 +134,10 @@ structures = {
 		id = "uint32_t, $-rem";						// Bereich 1 - MAX_BELL_FRAMES, unique, 0 = nicht konfiguriert
 		relaisID = "uint32_t, $-rem";				// Bereich 1 - MAX_RELAIS, ID des Relais oder Läutautomaten
 		type = "uint8_t, $-rem";					// Typ, Relais oder Läuteautomat
-		startOffsMin = "uint8_t, $-rem";			// Start-Offset in Minuten
-		startOffsSec = "uint8_t, $-rem";			// Start-Offset in Sekunden
-		durationMin = "uint8_t, $-rem";				// Dauer in Minuten
-		durationSec = "uint8_t, $-rem";				// Dauer in Sekunden
+		startOffsMin = "uint8_t, $-rem, $-log_iu";	// Start-Offset in Minuten
+		startOffsSec = "uint8_t, $-rem, $-log_iu";	// Start-Offset in Sekunden
+		durationMin = "uint8_t, $-rem, $-log_iu";	// Dauer in Minuten
+		durationSec = "uint8_t, $-rem, $-log_iu";	// Dauer in Sekunden
 //		szName = "$-utf-8, MAX_NAME_LENGTH, $-rem";	// Framename, fix formatiert: "REL-rrr/START-mm:ss/DAUER-mm:ss/Rel.Name" oder "LA-rrr/START-mm:ss/DAUER-mm:ss/Rel.Name" (z. B.: "REL-117/START-02:15/DAUER-00:30/Glocke 3 Ges")
 	};
 

+ 1 - 1
app/visu/main.cpp

@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
 
     /////////////////////////////////////////////////////////////////////////
 
-    //qputenv("QT_IM_MODULE", QByteArray("QtFreeVirtualKeyboard"));
+    qputenv("QT_IM_MODULE", QByteArray("QtFreeVirtualKeyboard"));
 
     /////////////////////////////////////////////////////////////////////////
 

+ 6 - 1
app/visu/qml.qrc

@@ -2,7 +2,6 @@
     <qresource prefix="/">
         <file>qml/main.qml</file>
         <file>qml/appctrl.qml</file>
-        <file>qml/shm.qml</file>
         <file>img/ata64.png</file>
         <file>img/blank.png</file>
         <file>img/header.png</file>
@@ -10,5 +9,11 @@
         <file>img/next.png</file>
         <file>img/prev.png</file>
         <file>img/usb64.png</file>
+        <file>qml/ifedit.qml</file>
+        <file>qml/Ip4Address.qml</file>
+        <file>qml/sysinfo.qml</file>
+        <file>qml/globals.js</file>
+        <file>qml/NavButton.qml</file>
+        <file>qml/stgdev.qml</file>
     </qresource>
 </RCC>

+ 176 - 0
app/visu/qml/Ip4Address.qml

@@ -0,0 +1,176 @@
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import QtQuick.Controls 1.5
+import QtQuick.Controls.Styles 1.4
+
+Item {
+	property double address: 0
+	signal addressModified()
+	
+	function setAddrByte(bnum, val)
+	{
+		if(bnum >= 0 && bnum < 4)
+		{
+			var shft = bnum * 8;
+			var mask = ~(0x000000FF << shft)
+			var newv = (address & mask) | (parseInt(val) << shft);
+			if(address !== newv)
+			{
+				address = newv;
+				addressModified();
+			}
+		}
+	}
+
+	Rectangle {
+		x: 0
+		y: 0
+	    width: 40
+	    height: 25
+		border.width: 1
+		border.color: "black"
+	    TextInput {
+	    	id: idb3
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignVCenter
+	        font.pointSize: 8
+	        inputMethodHints: Qt.ImhDigitsOnly
+	        validator: IntValidator{bottom: 0; top: 255;}
+            text: (parseInt(address, 10) >> 24) & 0xFF
+            KeyNavigation.tab: idb2
+ 			onAccepted: {
+ 				setAddrByte(3, text);
+            }
+			onActiveFocusChanged: {
+				if(!activeFocus)
+	 				setAddrByte(3, text);
+	 			else
+	 				selectAll();
+			}
+	    }
+	}
+	Rectangle {
+		x: 40
+		y: 0
+	    width: 10
+	    height: 25
+	    Text {
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignBottom
+	        font.pointSize: 8
+	        text: "."
+	    }
+	}
+	Rectangle {
+		x: 50
+		y: 0
+	    width: 40
+	    height: 25
+		border.width: 1
+		border.color: "black"
+	    TextInput {
+	    	id: idb2
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignVCenter
+	        font.pointSize: 8
+	        inputMethodHints: Qt.ImhDigitsOnly
+	        validator: IntValidator{bottom: 0; top: 255;}
+            text: (parseInt(address, 10) >> 16) & 0xFF
+            KeyNavigation.tab: idb1
+ 			onAccepted: {
+ 				setAddrByte(2, text);
+            }
+			onActiveFocusChanged: {
+				if(!activeFocus)
+	 				setAddrByte(2, text);
+	 			else
+	 				selectAll();
+			}
+	    }
+	}
+	Rectangle {
+		x: 90
+		y: 0
+	    width: 10
+	    height: 25
+	    Text {
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignBottom
+	        font.pointSize: 8
+	        text: "."
+	    }
+	}
+	Rectangle {
+		x: 100
+		y: 0
+	    width: 40
+	    height: 25
+		border.width: 1
+		border.color: "black"
+	    TextInput {
+	    	id: idb1
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignVCenter
+	        font.pointSize: 8
+	        inputMethodHints: Qt.ImhDigitsOnly
+	        validator: IntValidator{bottom: 0; top: 255;}
+            text: (parseInt(address, 10) >> 8) & 0xFF
+            KeyNavigation.tab: idb0
+ 			onAccepted: {
+ 				setAddrByte(1, text);
+            }
+			onActiveFocusChanged: {
+				if(!activeFocus)
+	 				setAddrByte(1, text);
+	 			else
+	 				selectAll();
+			}
+	    }
+	}
+	Rectangle {
+		x: 140
+		y: 0
+	    width: 10
+	    height: 25
+	    Text {
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignBottom
+	        font.pointSize: 8
+	        text: "."
+	    }
+	}
+	Rectangle {
+		x: 150
+		y: 0
+	    width: 40
+	    height: 25
+		border.width: 1
+		border.color: "black"
+	    TextInput {
+	    	id: idb0
+            anchors.fill: parent
+			horizontalAlignment: Text.AlignHCenter
+			verticalAlignment: Text.AlignVCenter
+	        font.pointSize: 8
+	        inputMethodHints: Qt.ImhDigitsOnly
+	        validator: IntValidator{bottom: 0; top: 255;}
+            text: parseInt(address, 10) & 0xFF
+            KeyNavigation.tab: idb3
+ 			onAccepted: {
+ 				setAddrByte(0, text);
+            }
+			onActiveFocusChanged: {
+				if(!activeFocus)
+	 				setAddrByte(0, text);
+	 			else
+	 				selectAll();
+			}
+	    }
+	}
+}

+ 9 - 0
app/visu/qml/NavButton.qml

@@ -0,0 +1,9 @@
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import QtQuick.Controls 2.0
+import QtQuick.Controls.Styles 1.4
+
+TabButton {
+	id: idInner
+	Component.onCompleted: { idInner.font.pointSize = 8; }
+}

+ 55 - 70
app/visu/qml/appctrl.qml

@@ -1,13 +1,15 @@
 import QtQuick 2.6
 import QtQuick.Window 2.2
-import QtQuick.Controls 1.5
+import QtQuick.Controls 1.4 as Ctrl14
+import QtQuick.Controls 2.0
 import QtQuick.Controls.Styles 1.4
-import QtQuick.Controls.Private 1.0
 import com.gfa.ipc.appctrl 1.0
+import com.gfa.shm._oem_ 1.0
+import "globals.js" as Globals
 
 Rectangle {
-    width: 800
-    height: 480
+    width: Screen.width
+    height: Screen.height
     
     function stateColor(state)
     {
@@ -37,51 +39,21 @@ Rectangle {
 
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
-	Rectangle {
-        x: 10
-        y: 10
-        width: parent.width - 20
-        height: 30
-        radius: 5
-		border.width: 1
-		border.color: "black"
-        color: "lightgreen"
-		Image {
-            anchors.left: parent.left
-			anchors.verticalCenter: parent.verticalCenter
-			fillMode: Image.PreserveAspectFit
-			height: parent.height
-            source: "qrc:/img/prev.png"
-			MouseArea {
-				anchors.fill: parent
-                onClicked: { idPageLoader.source = "shm.qml" }
+	TabBar {
+		id: idTabBar
+		width: parent.width
+		currentIndex: 0
+
+		Repeater {
+			id: idRep
+			model: Globals.tabBarModel
+
+			NavButton {
+				text: modelData[0]
+				onClicked: { idPageLoader.source = modelData[1]; }
+				width: idTabBar.width / idRep.count
 			}
 		}
-	    Text {
-	        font.pixelSize: 16
-	        font.bold: true
-			anchors.verticalCenter: parent.verticalCenter
-            anchors.centerIn: parent
-	        text: "GfA App Control"
-	    }
-		Image {
-            anchors.right: parent.right
-			anchors.verticalCenter: parent.verticalCenter
-			fillMode: Image.PreserveAspectFit
-			height: parent.height
-            source: "qrc:/img/blank.png"
-		}
-/*		Image {
-            anchors.right: parent.right
-			anchors.verticalCenter: parent.verticalCenter
-			fillMode: Image.PreserveAspectFit
-			height: parent.height
-            source: "qrc:/img/next.png"
-			MouseArea {
-		        anchors.fill: parent
-				onClicked: { idPageLoader.source = "stgdev.qml" }
-			}
-		}*/
 	}
 
 	/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -203,6 +175,19 @@ Rectangle {
 		        text: "VM Size KiB:"
 		    }
 		}
+
+	    Rectangle {
+	        x: 0
+	        y: 380
+	        height: 30
+	        width: parent.width
+			Ctrl14.Button {
+	            text: "Quit"
+	            anchors.fill: parent
+	            onClicked: Qt.quit()
+				style: idButtonStyle
+			}
+	    }
 	}
 
 	/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -355,7 +340,7 @@ Rectangle {
 	        y: 300
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            anchors.fill: parent
 				style: idButtonStyle
 	            enabled: (parent.parent.appInfo.state === QGfaAppCtrl.STATE_RUNNING || parent.parent.appInfo.state === QGfaAppCtrl.STATE_PAUSED)
@@ -369,7 +354,7 @@ Rectangle {
 	        y: 340
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Stop"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -383,7 +368,7 @@ Rectangle {
 	        y: 380
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Kill"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -396,12 +381,12 @@ Rectangle {
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
     Rectangle {
-        x: 660
+        x: 270
         y: 50
         width: 120
         height: 420
 
-        property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_DATALOGGER]
+        property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_MQTTCL]
 
 		Rectangle {
 	        x: 0
@@ -543,7 +528,7 @@ Rectangle {
 	        y: 300
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            anchors.fill: parent
 				style: idButtonStyle
 	            enabled: (parent.parent.appInfo.state === QGfaAppCtrl.STATE_RUNNING || parent.parent.appInfo.state === QGfaAppCtrl.STATE_PAUSED)
@@ -557,7 +542,7 @@ Rectangle {
 	        y: 340
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Stop"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -571,7 +556,7 @@ Rectangle {
 	        y: 380
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Kill"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -584,12 +569,12 @@ Rectangle {
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
     Rectangle {
-        x: 270
+        x: 400
         y: 50
         width: 120
         height: 420
 
-        property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_SUMMARIST]
+		property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_REST]
 
 		Rectangle {
 	        x: 0
@@ -731,7 +716,7 @@ Rectangle {
 	        y: 300
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            anchors.fill: parent
 				style: idButtonStyle
 	            enabled: (parent.parent.appInfo.state === QGfaAppCtrl.STATE_RUNNING || parent.parent.appInfo.state === QGfaAppCtrl.STATE_PAUSED)
@@ -745,7 +730,7 @@ Rectangle {
 	        y: 340
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Stop"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -759,7 +744,7 @@ Rectangle {
 	        y: 380
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Kill"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -772,12 +757,12 @@ Rectangle {
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
     Rectangle {
-        x: 400
+        x: 530
         y: 50
         width: 120
         height: 420
 
-		property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_MQTTCL]
+		property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_DATALOGGER]
 
 		Rectangle {
 	        x: 0
@@ -919,7 +904,7 @@ Rectangle {
 	        y: 300
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            anchors.fill: parent
 				style: idButtonStyle
 	            enabled: (parent.parent.appInfo.state === QGfaAppCtrl.STATE_RUNNING || parent.parent.appInfo.state === QGfaAppCtrl.STATE_PAUSED)
@@ -933,7 +918,7 @@ Rectangle {
 	        y: 340
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Stop"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -947,7 +932,7 @@ Rectangle {
 	        y: 380
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Kill"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -960,12 +945,12 @@ Rectangle {
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
     Rectangle {
-        x: 530
+        x: 660
         y: 50
         width: 120
         height: 420
 
-		property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_REST]
+        property var appInfo: qGfaAppCtrl.appInfo[QGfaAppCtrl.APP_INDEX_SUMMARIST]
 
 		Rectangle {
 	        x: 0
@@ -1107,7 +1092,7 @@ Rectangle {
 	        y: 300
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            anchors.fill: parent
 				style: idButtonStyle
 	            enabled: (parent.parent.appInfo.state === QGfaAppCtrl.STATE_RUNNING || parent.parent.appInfo.state === QGfaAppCtrl.STATE_PAUSED)
@@ -1121,7 +1106,7 @@ Rectangle {
 	        y: 340
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Stop"
 				style: idButtonStyle
 	            anchors.fill: parent
@@ -1135,7 +1120,7 @@ Rectangle {
 	        y: 380
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Kill"
 				style: idButtonStyle
 	            anchors.fill: parent

+ 28 - 0
app/visu/qml/globals.js

@@ -0,0 +1,28 @@
+var tabBarModel = [["App Control", "appctrl.qml"], ["SysInfo", "sysinfo.qml"], ["Network", "ifedit.qml"], ["Storage Dev.", "stgdev.qml"]];
+var zeroBasedLabels = false;
+var ledGrey		= "qrc:/img/led-grey24.png";
+var ledGreen	= "qrc:/img/led-green24.png";
+var ledRed		= "qrc:/img/led-red24.png";
+
+function getIoModuleXPos(index)
+{
+	if(index >= 9)
+		index -= 9;
+    var cx = (800 - 20) / 9;
+    return 10 + index * cx + index * 1.25;
+}
+
+function getIoModuleYPos(index)
+{
+	return (index < 9) ? 50 : 265;
+}
+
+function isInternalIo(index)
+{
+	return (index < 2);
+}
+
+function trunc(num)
+{
+	return parseInt(num, 10);
+}

+ 495 - 0
app/visu/qml/ifedit.qml

@@ -0,0 +1,495 @@
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import QtQuick.Controls 2.0
+//import QtQuick.Controls 1.5
+import QtQuick.Controls 1.4 as Ctrl14
+import QtQuick.Controls.Styles 1.4
+import com.gfa.ipc.appctrl 1.0
+import "globals.js" as Globals
+import QtQuick.FreeVirtualKeyboard 1.0
+
+Rectangle {
+    id: idEdit
+    width: Screen.width
+    height: Screen.height
+
+    property bool isDirty: false
+    property bool ifUpDownInProgress: false
+    
+    function updateUI(sel)
+    {
+		if(sel >= 0)
+		{
+			switch(qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].method)
+			{
+			case QInterface.IM_Static:
+				idStatic.visible = true;
+				idDhcp.visible = false;
+				idMethStatic.checked = true;
+				idIfUpDownOutput.visible = true;
+				break;
+			case QInterface.IM_Dhcp:
+				idStatic.visible = false;
+				idDhcp.visible = true;
+				idMethDhcp.checked = true;
+				idIfUpDownOutput.visible = true;
+				break;
+			default:
+				idStatic.visible = false;
+				idDhcp.visible = false;
+				idMethStatic.checked = false;
+				idMethDhcp.checked = false;
+				idIfUpDownOutput.visible = false;
+				break;
+			}
+
+			if(sel > 0)
+			{
+				idAddrS.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.ipAddress.addr;
+				idSubnetS.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.netMask.addr;
+				idGateS.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.gateway.addr;
+				idDnsS1.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.dnsServer[0].addr;
+				idDnsS2.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.dnsServer[1].addr;
+				idDnsS3.address = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[sel].inet.stat.dnsServer[2].addr;
+			}
+		}
+    }
+
+	Connections {
+		target: qGfaAppCtrl.sysInfo.netInterfaceInfo
+
+		onIfUpDown: {
+			console.log("IfUpDown: " + msg);
+			idIfUpDownText.append(msg.trim());
+		}
+
+		onIfUpDownCompleted: {
+			switch(ctx)
+			{
+			case QNetworkInterfaces.UDC_Start:
+				console.log("ifup: " + code);
+            	ifUpDownInProgress = false;
+				break;
+			case QNetworkInterfaces.UDC_Stop:
+				console.log("ifdown: " + code);
+            	ifUpDownInProgress = false;
+				break;
+			case QNetworkInterfaces.UDC_Restart:
+				console.log("ifupdown: " + code);
+            	ifUpDownInProgress = false;
+				break;
+			}
+		}
+
+		onError: {
+			console.log("Error: " + msg);
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	TabBar {
+		id: idTabBar
+		width: parent.width
+		currentIndex: 2
+
+		Repeater {
+			id: idRep
+			model: Globals.tabBarModel
+
+			NavButton {
+				text: modelData[0]
+				onClicked: { idPageLoader.source = modelData[1]; }
+				width: idTabBar.width / idRep.count
+			}
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Ctrl14.TableView {
+		id: idItfList
+		height: 420
+		width:	180
+		x: 10
+		y: 50
+		headerVisible: false
+        style: TableViewStyle {
+        	itemDelegate: idTableViewItemStyle
+        }
+		model:	qGfaAppCtrl.sysInfo.netInterfaceInfo.schemaModel
+		selection.onSelectionChanged:
+		{
+			idIfUpDownText.text = "";
+			updateUI(idItfList.currentRow);
+		}
+
+		Ctrl14.TableViewColumn {
+			role: "name"
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Ctrl14.ExclusiveGroup { id: idMethExGroup }
+
+	Rectangle {
+		id: idMethGroup
+	    x: 200
+	    y: 50
+	    width: 590
+	    height: 45
+        radius: 5
+		border.width: 1
+		border.color: "black"
+		visible: (idItfList.currentRow > 0)
+		
+		property int method: (idItfList.currentRow > 0) ? qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].method : 0
+
+		Ctrl14.RadioButton {
+			x: 10
+			y: 10
+			id: idMethStatic
+			exclusiveGroup: idMethExGroup
+			style: RadioButtonStyle {
+                label: Text {
+                	text: qsTr("Static")
+					font.pointSize: 8
+				}
+			}
+			onClicked: {
+				if(idItfList.currentRow > 0)
+				{
+					if(checked)
+					{
+						qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].method = QInterface.IM_Static;
+						idStatic.visible = true;
+						idDhcp.visible = false;
+						isDirty = true;
+					}
+				}
+			}
+		}
+
+		Ctrl14.RadioButton {
+			x: 100
+			y: 10
+			id: idMethDhcp
+			exclusiveGroup: idMethExGroup
+			style: RadioButtonStyle {
+                label: Text {
+                	text: qsTr("DHCP")
+					font.pointSize: 8
+				}
+			}
+			onClicked: {
+				if(idItfList.currentRow > 0)
+				{
+					if(checked)
+					{
+						qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].method = QInterface.IM_Dhcp;
+						idStatic.visible = false;
+						idDhcp.visible = true;
+						isDirty = true;
+					}
+				}
+			}
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Rectangle {
+	    id: idStatic
+	    x: 200
+	    y: 105
+	    width: 590
+	    height: 115
+        radius: 5
+		border.width: 1
+		border.color: "black"
+		visible: false
+
+	    Text {
+	    	x: 10
+	    	y: 10
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "Address:"
+	    }
+
+		Ip4Address {
+	    	id: idAddrS
+	    	x: 90
+	    	y: 10
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("Address modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.ipAddress.addr = idAddrS.address;
+	    	}
+		}
+
+	    Text {
+	    	x: 10
+	    	y: 45
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "Netmask:"
+	    }
+
+		Ip4Address {
+	    	id: idSubnetS
+	    	x: 90
+	    	y: 45
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("Netmask modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.netMask.addr = idSubnetS.address;
+	    	}
+		}
+
+	    Text {
+	    	x: 10
+	    	y: 80
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "Gateway:"
+	    }
+
+		Ip4Address {
+	    	id: idGateS
+	    	x: 90
+	    	y: 80
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("Gateway modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.gateway.addr = idGateS.address;
+	    	}
+		}
+
+	    Text {
+	    	x: 330
+	    	y: 10
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "DNS 1:"
+	    }
+
+		Ip4Address {
+	    	id: idDnsS1
+	    	x: 390
+	    	y: 10
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("DNS 1 modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.dnsServer[0].addr = idDnsS1.address;
+	    	}
+		}
+
+	    Text {
+	    	x: 330
+	    	y: 45
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "DNS 2:"
+	    }
+
+		Ip4Address {
+	    	id: idDnsS2
+	    	x: 390
+	    	y: 45
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("DNS 2 modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.dnsServer[1].addr = idDnsS2.address;
+	    	}
+		}
+
+	    Text {
+	    	x: 330
+	    	y: 80
+	        font.pointSize: 8
+			verticalAlignment: Text.AlignVCenter
+	        text: "DNS 3:"
+	    }
+
+		Ip4Address {
+	    	id: idDnsS3
+	    	x: 390
+	    	y: 80
+	    	address: 0
+	    	onAddressModified: {
+				isDirty = true;
+	    		console.log("DNS 3 modified: " + address);
+	    		if(idItfList.currentRow > 0)
+		    		qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow].inet.stat.dnsServer[2].addr = idDnsS3.address;
+	    	}
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Rectangle {
+	    id: idDhcp
+	    x: 200
+	    y: 105
+	    width: 590
+	    height: 115
+        radius: 5
+		border.width: 1
+		border.color: "black"
+		visible: false
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Rectangle {
+	    id: idIfUpDownOutput
+	    x: 200
+	    y: 230
+	    width: 590
+	    height: 180
+		visible: false
+
+		TextArea {
+		    id: idIfUpDownText
+		    anchors.fill: parent
+		    readOnly: true
+		    selectByMouse: false
+		    selectByKeyboard: false
+	        font.pointSize: 8
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Rectangle {
+	    id: idButtons
+	    x: 200
+	    y: 420
+	    width: 590
+	    height: 50
+        radius: 5
+		border.width: 1
+		border.color: "black"
+
+		Ctrl14.Button {
+			x: 10
+			y: 10
+			width: 100
+            text: "Save"
+            enabled: isDirty && !ifUpDownInProgress
+            onClicked: {
+				var itf = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow];
+				isDirty = false;
+            	console.log("Save");
+            	qGfaAppCtrl.sysInfo.netInterfaceInfo.save();
+            }
+			style: idButtonStyle
+		}
+
+		Ctrl14.Button {
+			x: 120
+			y: 10
+			width: 100
+            text: "Cancel"
+            enabled: isDirty && !ifUpDownInProgress
+            onClicked: {
+				isDirty = false;
+            	console.log("Cancel");
+            	qGfaAppCtrl.sysInfo.netInterfaceInfo.reload();
+				updateUI(idItfList.currentRow);
+            }
+			style: idButtonStyle
+		}
+
+		Ctrl14.Button {
+			x: 260
+			y: 10
+			width: 100
+            text: "Start"
+            enabled: !isDirty && !ifUpDownInProgress && (idItfList.currentRow > 0)
+            onClicked: {
+				var itf = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow];
+            	console.log("Start");
+            	ifUpDownInProgress = true;
+				idIfUpDownText.text = "";
+            	qGfaAppCtrl.sysInfo.netInterfaceInfo.startInterface(itf);
+            }
+			style: idButtonStyle
+		}
+
+		Ctrl14.Button {
+			x: 370
+			y: 10
+			width: 100
+            text: "Stop"
+            enabled: !isDirty && !ifUpDownInProgress && (idItfList.currentRow > 0)
+            onClicked: {
+				var itf = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow];
+            	console.log("Stop");
+            	ifUpDownInProgress = true;
+				idIfUpDownText.text = "";
+            	qGfaAppCtrl.sysInfo.netInterfaceInfo.stopInterface(itf);
+            }
+			style: idButtonStyle
+		}
+
+		Ctrl14.Button {
+			x: 480
+			y: 10
+			width: 100
+            text: "Restart"
+            enabled: !isDirty && !ifUpDownInProgress && (idItfList.currentRow > 0)
+            onClicked: {
+				var itf = qGfaAppCtrl.sysInfo.netInterfaceInfo.interfaces[idItfList.currentRow];
+            	console.log("Restart");
+            	ifUpDownInProgress = true;
+				idIfUpDownText.text = "";
+            	qGfaAppCtrl.sysInfo.netInterfaceInfo.restartInterface(itf);
+            }
+			style: idButtonStyle
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+    InputPanel {
+           id: inputPanel
+           z: 99
+           y: idEdit.height
+           anchors.left: parent.left
+           anchors.right: parent.right
+
+           states: State {
+               name: "visible"
+               when: Qt.inputMethod.visible
+               PropertyChanges {
+                   target: inputPanel
+                   y: idEdit.height - inputPanel.height
+               }
+           }
+           transitions: Transition {
+               from: ""
+               to: "visible"
+               reversible: true
+               ParallelAnimation {
+                   NumberAnimation {
+                       properties: "y"
+                       duration: 150
+                       easing.type: Easing.InOutQuad
+                   }
+               }
+           }
+       }
+}

+ 3 - 4
app/visu/qml/main.qml

@@ -10,7 +10,6 @@ Window {
     width: 800
     height: 480
 
-/*
 	Component {
 		id: imageDelegate
 		Item {
@@ -18,7 +17,7 @@ Window {
 				anchors.centerIn: parent
 				fillMode: Image.PreserveAspectFit
 				height:20
-	            source: (styleData.value) === "usb" ? "qrc:/img/usb64.png" : ((styleData.value) === "ata" ? "qrc:/img/ata64.png" : "qrc:/img/mmc64.png")
+	            source: (styleData.value) === "usb" ? "qrc:/img/usb64.png" : (((styleData.value) === "ata" || (styleData.value) === "int") ? "qrc:/img/ata64.png" : "qrc:/img/mmc64.png")
 			}
 		}
 	}
@@ -33,7 +32,7 @@ Window {
 			color: styleData.textColor
             text: styleData.value
 		}			
-	}*/
+	}
 
 	Component {
 		id: idButtonStyle
@@ -105,6 +104,6 @@ Window {
 
 	Loader {
 		id: idPageLoader
-        source: "shm.qml"
+        source: "appctrl.qml"
 	}
 }

+ 114 - 0
app/visu/qml/stgdev.qml

@@ -0,0 +1,114 @@
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import QtQuick.Controls 1.4 as Ctrl14
+import QtQuick.Controls 2.0
+//import QtQuick.Controls 1.5
+import QtQuick.Controls.Styles 1.4
+import com.gfa.ipc.appctrl 1.0
+import "globals.js" as Globals
+
+/*
+	Available Roles (Columns):
+
+	DiskName
+	DiskDevNode
+	DiskDevType
+	DiskVendorName
+	DiskVendorID
+	DiskProductID
+	PartFsLabel
+	PartFsType
+	PartFsVersion
+	PartDevNode
+	PartMountPoint
+	PartSize
+	PartFsSize
+	PartFsFree
+	PartFsUsed
+*/
+
+Rectangle {
+    width: Screen.width
+    height: Screen.height
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	TabBar {
+		id: idTabBar
+		width: parent.width
+		currentIndex: 3
+
+		Repeater {
+			id: idRep
+			model: Globals.tabBarModel
+
+			NavButton {
+				text: modelData[0]
+				onClicked: { idPageLoader.source = modelData[1]; }
+				width: idTabBar.width / idRep.count
+			}
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Ctrl14.TableView {
+        x: 10
+        y: 50
+        width: parent.width - 20
+        height: 420
+        style: TableViewStyle {
+        	itemDelegate: idTableViewItemStyle
+        	headerDelegate: idTableViewHeaderStyle
+        }
+
+		Ctrl14.TableViewColumn {
+			role: "DiskDevType"
+			width: 32
+			delegate:imageDelegate
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 120
+			title: "Disk"
+			role: "DiskName"
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 80
+			title: "Volume"
+			role: "PartFsLabel"
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 80
+			title: "Size"
+			role: "PartSize"
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 80
+			title: "Used"
+			role: "PartFsUsed"
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 80
+			title: "Free"
+			role: "PartFsFree"
+		}
+
+		Ctrl14.TableViewColumn {
+			width: 145
+			title: "Node"
+			role: "PartDevNode"
+		}
+
+		Ctrl14.TableViewColumn {
+			title: "Mountpoint"
+			role: "PartMountPoint"
+		}
+
+		model: qGfaAppCtrl.sysInfo.stgDev
+	}
+}

+ 20 - 37
app/visu/qml/sysinfo.qml

@@ -1,13 +1,15 @@
 import QtQuick 2.6
 import QtQuick.Window 2.2
-import QtQuick.Controls 1.5
+import QtQuick.Controls 1.4 as Ctrl14
+import QtQuick.Controls 2.0
 import QtQuick.Controls.Styles 1.4
-import QtQuick.Controls.Private 1.0
+//import QtQuick.Controls.Private 1.0
 import com.gfa.ipc.appctrl 1.0
+import "globals.js" as Globals
 
 Rectangle {
-    width: 800
-    height: 480
+    width: Screen.width
+    height: Screen.height
 
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -47,38 +49,19 @@ Rectangle {
 
 	/////////////////////////////////////////////////////////////////////////////////////////////////
 
-	Rectangle {
-        x: 10
-        y: 10
-        width: parent.width - 20
-        height: 30
-        radius: 5
-		border.width: 1
-		border.color: "black"
-        color: qGfaAppCtrl.sysInfoRunning ? "lightgreen" : "red"
-		Image {
-            anchors.left: parent.left
-			anchors.verticalCenter: parent.verticalCenter
-			fillMode: Image.PreserveAspectFit
-			height: parent.height
-            source: "qrc:/img/blank.png"
-		}
-	    Text {
-	        font.pixelSize: 16
-	        font.bold: true
-			anchors.verticalCenter: parent.verticalCenter
-            anchors.centerIn: parent
-	        text: "System Info"
-	    }
-		Image {
-            anchors.right: parent.right
-			anchors.verticalCenter: parent.verticalCenter
-			fillMode: Image.PreserveAspectFit
-			height: parent.height
-            source: "qrc:/img/next.png"
-			MouseArea {
-		        anchors.fill: parent
-				onClicked: { idPageLoader.source = "qml/appctrl.qml" }
+	TabBar {
+		id: idTabBar
+		width: parent.width
+		currentIndex: 1
+
+		Repeater {
+			id: idRep
+			model: Globals.tabBarModel
+
+			NavButton {
+				text: modelData[0]
+				onClicked: { idPageLoader.source = modelData[1]; }
+				width: idTabBar.width / idRep.count
 			}
 		}
 	}
@@ -213,7 +196,7 @@ Rectangle {
 	        y: 350
 	        height: 30
 	        width: parent.width
-			Button {
+			Ctrl14.Button {
 	            text: "Exit"
 	            anchors.fill: parent
 	            onClicked: Qt.quit()

+ 1 - 2
svc/datalogger/main.cpp

@@ -429,8 +429,7 @@ int main(int argc, char **argv)
 			if(!dlc.Sleep(bTimerUnderrun, true))
 			{
 				g_fRun = g_fPauseImp = g_fPauseCmd = false;
-				g_fZombie = true;
-				g_lf.Error("CDataLoggerClock::Sleep Error!\n", t);
+				g_lf.Error("CDataLoggerClock::Sleep: Interrupted!\n", t);
 				break;
 			}
 

+ 133 - 98
svc/mqttcl/cfg/README.html → svc/mqttcl/cfg/README.htm

@@ -4,7 +4,7 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
     <meta http-equiv="X-UA-Compatible" content="IE=9">
-    <title>Markdown preview</title>
+    <title>Mögliche Parameter in mqtt.conf.json</title>
     <style>body {
   box-sizing: border-box;
   min-width: 200px;
@@ -715,7 +715,7 @@
     <article class="markdown-body">
       <p data-sourcepos="1:1-1:42"><strong>Mögliche Parameter in mqtt.conf.json:</strong></p>
 <h2 data-sourcepos="2:1-2:2"></h2>
-<ul data-sourcepos="5:1-112:15">
+<ul data-sourcepos="5:1-135:15">
 <li data-sourcepos="5:1-7:0">
 <p data-sourcepos="5:3-5:17"><strong>brokerAddr:</strong></p>
 <ul data-sourcepos="6:2-7:0">
@@ -751,7 +751,7 @@
 <ul data-sourcepos="24:2-27:0">
 <li data-sourcepos="24:2-24:12">Optional.</li>
 <li data-sourcepos="25:2-25:85">Wird u. a. verwendet, um zusammen mit der SHM-UUID das Topic-Prefix zu generieren.</li>
-<li data-sourcepos="26:2-27:0">Default: &quot;GfA&quot;.</li>
+<li data-sourcepos="26:2-27:0">Default: Leer, wenn nicht angegeben.</li>
 </ul>
 </li>
 <li data-sourcepos="28:1-32:0">
@@ -759,136 +759,171 @@
 <ul data-sourcepos="29:2-32:0">
 <li data-sourcepos="29:2-29:12">Optional.</li>
 <li data-sourcepos="30:2-30:85">Wird u. a. verwendet, um zusammen mit der SHM-UUID das Topic-Prefix zu generieren.</li>
-<li data-sourcepos="31:2-32:0">Default: Automatisch generiert aus devicePrefix und MAC-Adresse.</li>
+<li data-sourcepos="31:2-32:0">Default: Automatisch generiert aus devicePrefix und MAC-Adresse, oder nur MAC-Adresse, wenn kein devicePrefix angegeben.</li>
 </ul>
 </li>
-<li data-sourcepos="33:1-36:0">
-<p data-sourcepos="33:3-33:18"><strong>topicPrefix:</strong></p>
-<ul data-sourcepos="34:2-36:0">
+<li data-sourcepos="33:1-37:0">
+<p data-sourcepos="33:3-33:25"><strong>disableTopicPrefix:</strong></p>
+<ul data-sourcepos="34:2-37:0">
 <li data-sourcepos="34:2-34:12">Optional.</li>
-<li data-sourcepos="35:2-36:0">Ersetzt, wenn angegeben, das Topic-Prefix.</li>
+<li data-sourcepos="35:2-35:46">Wenn true, wird kein Topic-Prefix gesendet.</li>
+<li data-sourcepos="36:2-37:0">Default: false.</li>
 </ul>
 </li>
-<li data-sourcepos="37:1-41:0">
-<p data-sourcepos="37:3-37:14"><strong>tlsMode:</strong></p>
-<ul data-sourcepos="38:2-41:0">
-<li data-sourcepos="38:2-38:12">Optional.</li>
-<li data-sourcepos="39:2-39:67">0 = kein TLS, 1 = TLS mit Zertifikat, 2 = TLS mit Preshared Key.</li>
-<li data-sourcepos="40:2-41:0">Default: 0 (kein TLS).</li>
+<li data-sourcepos="38:1-42:0">
+<p data-sourcepos="38:3-38:18"><strong>topicPrefix:</strong></p>
+<ul data-sourcepos="39:2-42:0">
+<li data-sourcepos="39:2-39:12">Optional.</li>
+<li data-sourcepos="40:2-40:39">Nur wenn disableTopicPrefix = false.</li>
+<li data-sourcepos="41:2-42:0">Ersetzt, wenn angegeben, das Topic-Prefix.</li>
 </ul>
 </li>
-<li data-sourcepos="42:1-48:0">
-<p data-sourcepos="42:3-42:47"><strong>tlsCaCrtFile, tlsClKeyFile, tlsClCrtFile:</strong></p>
-<ul data-sourcepos="43:2-48:0">
-<li data-sourcepos="43:2-43:33">Erforderlich wenn tlsMode = 1.</li>
-<li data-sourcepos="44:2-48:0">Pfad zu den folgenden Dateien:
-<ul data-sourcepos="45:3-48:0">
-<li data-sourcepos="45:3-45:75"><em><strong>tlsCaCrtFile</strong></em>: öffentliches Zertifikat der Certificate Authority.</li>
-<li data-sourcepos="46:3-46:55"><em><strong>tlsClKeyFile</strong></em>: privater Schlüssel des Client.</li>
-<li data-sourcepos="47:3-48:0"><em><strong>tlsClCrtFile</strong></em>: öffentliches Zertifikat zu diesem Schlüssel.</li>
+<li data-sourcepos="43:1-47:0">
+<p data-sourcepos="43:3-43:14"><strong>tlsMode:</strong></p>
+<ul data-sourcepos="44:2-47:0">
+<li data-sourcepos="44:2-44:12">Optional.</li>
+<li data-sourcepos="45:2-45:109">0 = kein TLS, 1 = TLS mit Zertifikat, 2 = TLS mit Preshared Key. Ungültige Werte werden auf 0 korrigiert!</li>
+<li data-sourcepos="46:2-47:0">Default: 0 (kein TLS).</li>
 </ul>
 </li>
+<li data-sourcepos="48:1-54:0">
+<p data-sourcepos="48:3-48:47"><strong>tlsCaCrtFile, tlsClKeyFile, tlsClCrtFile:</strong></p>
+<ul data-sourcepos="49:2-54:0">
+<li data-sourcepos="49:2-49:33">Erforderlich wenn tlsMode = 1.</li>
+<li data-sourcepos="50:2-54:0">Pfad zu den folgenden Dateien:
+<ul data-sourcepos="51:3-54:0">
+<li data-sourcepos="51:3-51:75"><em><strong>tlsCaCrtFile</strong></em>: öffentliches Zertifikat der Certificate Authority.</li>
+<li data-sourcepos="52:3-52:55"><em><strong>tlsClKeyFile</strong></em>: privater Schlüssel des Client.</li>
+<li data-sourcepos="53:3-54:0"><em><strong>tlsClCrtFile</strong></em>: öffentliches Zertifikat zu diesem Schlüssel.</li>
 </ul>
 </li>
-<li data-sourcepos="49:1-52:0">
-<p data-sourcepos="49:3-49:13"><strong>tlsPsk:</strong></p>
-<ul data-sourcepos="50:2-52:0">
-<li data-sourcepos="50:2-50:33">Erforderlich wenn tlsMode = 2.</li>
-<li data-sourcepos="51:2-52:0">Preshared Key als String im Hex-Format ohne führendes &quot;0x&quot;.</li>
 </ul>
 </li>
-<li data-sourcepos="53:1-56:0">
-<p data-sourcepos="53:3-53:22"><strong>lastWillMessage:</strong></p>
-<ul data-sourcepos="54:2-56:0">
-<li data-sourcepos="54:2-54:12">Optional.</li>
-<li data-sourcepos="55:2-56:0">Wenn angegeben, wird diese Nachricht als &quot;Last Will&quot; gepublished.</li>
+<li data-sourcepos="55:1-58:0">
+<p data-sourcepos="55:3-55:13"><strong>tlsPsk:</strong></p>
+<ul data-sourcepos="56:2-58:0">
+<li data-sourcepos="56:2-56:33">Erforderlich wenn tlsMode = 2.</li>
+<li data-sourcepos="57:2-58:0">Preshared Key als String im Hex-Format ohne führendes &quot;0x&quot;.</li>
 </ul>
 </li>
-<li data-sourcepos="57:1-62:0">
-<p data-sourcepos="57:3-57:20"><strong>lastWillTopic:</strong></p>
-<ul data-sourcepos="58:2-62:0">
-<li data-sourcepos="58:2-58:12">Optional.</li>
-<li data-sourcepos="59:2-59:41">Nur wenn lastWillMessage konfiguriert.</li>
-<li data-sourcepos="60:2-60:25">Topic des &quot;Last Will&quot;.</li>
-<li data-sourcepos="61:2-62:0">Default: &quot;LAST_WILL_CONNECT&quot;.</li>
+<li data-sourcepos="59:1-62:0">
+<p data-sourcepos="59:3-59:21"><strong>lastWillMsgStr:</strong></p>
+<ul data-sourcepos="60:2-62:0">
+<li data-sourcepos="60:2-60:12">Optional.</li>
+<li data-sourcepos="61:2-62:0">Wenn angegeben, wird diese Nachricht als &quot;Last Will&quot; gepublished.</li>
 </ul>
 </li>
-<li data-sourcepos="63:1-68:0">
-<p data-sourcepos="63:3-63:18"><strong>lastWillQos:</strong></p>
-<ul data-sourcepos="64:2-68:0">
+<li data-sourcepos="63:1-67:0">
+<p data-sourcepos="63:3-63:21"><strong>lastWillMsgInt:</strong></p>
+<ul data-sourcepos="64:2-67:0">
 <li data-sourcepos="64:2-64:12">Optional.</li>
-<li data-sourcepos="65:2-65:41">Nur wenn lastWillMessage konfiguriert.</li>
-<li data-sourcepos="66:2-66:38">Quality of Service des &quot;Last Will&quot;.</li>
-<li data-sourcepos="67:2-68:0">Default: Wert des defaultQos.</li>
+<li data-sourcepos="65:2-65:43">Nur wenn lastWillMsgStr nicht angegeben.</li>
+<li data-sourcepos="66:2-67:0">Wenn angegeben, wird dieser Wert als signed 64Bit-Wert binär als &quot;Last Will&quot; gepublished.</li>
 </ul>
 </li>
-<li data-sourcepos="69:1-74:0">
-<p data-sourcepos="69:3-69:21"><strong>lastWillRetain:</strong></p>
-<ul data-sourcepos="70:2-74:0">
-<li data-sourcepos="70:2-70:12">Optional.</li>
-<li data-sourcepos="71:2-71:41">Nur wenn lastWillMessage konfiguriert.</li>
-<li data-sourcepos="72:2-72:40">Retained-Einstellung des &quot;Last Will&quot;.</li>
-<li data-sourcepos="73:2-74:0">Default: false.</li>
+<li data-sourcepos="68:1-73:0">
+<p data-sourcepos="68:3-68:20"><strong>lastWillTopic:</strong></p>
+<ul data-sourcepos="69:2-73:0">
+<li data-sourcepos="69:2-69:12">Optional.</li>
+<li data-sourcepos="70:2-70:60">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.</li>
+<li data-sourcepos="71:2-71:25">Topic des &quot;Last Will&quot;.</li>
+<li data-sourcepos="72:2-73:0">Default: &quot;LWC&quot;.</li>
 </ul>
 </li>
-<li data-sourcepos="75:1-80:0">
-<p data-sourcepos="75:3-75:21"><strong>lastWillOnExit:</strong></p>
-<ul data-sourcepos="76:2-80:0">
-<li data-sourcepos="76:2-76:12">Optional.</li>
-<li data-sourcepos="77:2-77:41">Nur wenn lastWillMessage konfiguriert.</li>
-<li data-sourcepos="78:2-78:125">Wenn true, wird beim normalen Beenden des Clients eine &quot;Last Will&quot;-Message mit dem Wert von lastWillOnExitMsg gepublished.</li>
-<li data-sourcepos="79:2-80:0">Default: true.</li>
+<li data-sourcepos="74:1-79:0">
+<p data-sourcepos="74:3-74:18"><strong>lastWillQos:</strong></p>
+<ul data-sourcepos="75:2-79:0">
+<li data-sourcepos="75:2-75:12">Optional.</li>
+<li data-sourcepos="76:2-76:60">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.</li>
+<li data-sourcepos="77:2-77:38">Quality of Service des &quot;Last Will&quot;.</li>
+<li data-sourcepos="78:2-79:0">Default: Wert des defaultQos.</li>
 </ul>
 </li>
-<li data-sourcepos="81:1-86:0">
-<p data-sourcepos="81:3-81:24"><strong>lastWillOnExitMsg:</strong></p>
-<ul data-sourcepos="82:2-86:0">
-<li data-sourcepos="82:2-82:12">Optional.</li>
-<li data-sourcepos="83:2-83:67">Nur wenn lastWillMessage konfiguriert und lastWillOnExit = true.</li>
-<li data-sourcepos="84:2-84:69">Nachricht, die beim	normalen Beenden des Clients gepublished wird.</li>
-<li data-sourcepos="85:2-86:0">Default: lastWillMessage.</li>
+<li data-sourcepos="80:1-85:0">
+<p data-sourcepos="80:3-80:21"><strong>lastWillRetain:</strong></p>
+<ul data-sourcepos="81:2-85:0">
+<li data-sourcepos="81:2-81:12">Optional.</li>
+<li data-sourcepos="82:2-82:60">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.</li>
+<li data-sourcepos="83:2-83:40">Retained-Einstellung des &quot;Last Will&quot;.</li>
+<li data-sourcepos="84:2-85:0">Default: defaultRetain.</li>
 </ul>
 </li>
-<li data-sourcepos="87:1-90:0">
-<p data-sourcepos="87:3-87:21"><strong>connectMessage:</strong></p>
-<ul data-sourcepos="88:2-90:0">
-<li data-sourcepos="88:2-88:12">Optional.</li>
-<li data-sourcepos="89:2-90:0">Nachricht, die, wenn konfiguriert, beim Start des Clients gepublished wird.</li>
+<li data-sourcepos="86:1-91:0">
+<p data-sourcepos="86:3-86:21"><strong>lastWillOnExit:</strong></p>
+<ul data-sourcepos="87:2-91:0">
+<li data-sourcepos="87:2-87:12">Optional.</li>
+<li data-sourcepos="88:2-88:60">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.</li>
+<li data-sourcepos="89:2-89:159">Wenn true, wird auch beim normalen Beenden des Clients eine &quot;Last Will&quot;-Message mit dem Wert von lastWillOnExitMsgStr oder lastWillOnExitMsgInt gepublished.</li>
+<li data-sourcepos="90:2-91:0">Default: true.</li>
 </ul>
 </li>
-<li data-sourcepos="91:1-96:0">
-<p data-sourcepos="91:3-91:19"><strong>connectTopic:</strong></p>
-<ul data-sourcepos="92:2-96:0">
-<li data-sourcepos="92:2-92:12">Optional.</li>
-<li data-sourcepos="93:2-93:40">Nur wenn connectMessage konfiguriert.</li>
-<li data-sourcepos="94:2-94:68">Topic der Nachricht, die beim Start des Clients gepublished wird.</li>
-<li data-sourcepos="95:2-96:0">Default: lastWillTopic, wenn konfiguriert, sonst &quot;LAST_WILL_CONNECT&quot;.</li>
+<li data-sourcepos="92:1-97:0">
+<p data-sourcepos="92:3-92:27"><strong>lastWillOnExitMsgStr:</strong></p>
+<ul data-sourcepos="93:2-97:0">
+<li data-sourcepos="93:2-93:12">Optional.</li>
+<li data-sourcepos="94:2-94:90">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert ist und lastWillOnExit = true.</li>
+<li data-sourcepos="95:2-95:69">Nachricht, die beim	normalen Beenden des Clients gepublished wird.</li>
+<li data-sourcepos="96:2-97:0">Default: Wenn weder lastWillOnExitMsgStr noch lastWillOnExitMsgInt angegeben sind, wird lastWillOnExitMsgStr auf lastWillMsgStr gesetzt, sofern dieser konfiguriert ist, ansonsten wird lastWillOnExitMsgInt auf lastWillMsgInt gesetzt.</li>
 </ul>
 </li>
-<li data-sourcepos="97:1-102:0">
-<p data-sourcepos="97:3-97:17"><strong>connectQos:</strong></p>
-<ul data-sourcepos="98:2-102:0">
-<li data-sourcepos="98:2-98:12">Optional.</li>
-<li data-sourcepos="99:2-99:40">Nur wenn connectMessage konfiguriert.</li>
-<li data-sourcepos="100:2-100:41">Quality of Service der Startnachricht.</li>
-<li data-sourcepos="101:2-102:0">Default: defaultQos.</li>
+<li data-sourcepos="98:1-104:0">
+<p data-sourcepos="98:3-98:27"><strong>lastWillOnExitMsgInt:</strong></p>
+<ul data-sourcepos="99:2-104:0">
+<li data-sourcepos="99:2-99:12">Optional.</li>
+<li data-sourcepos="100:2-100:90">Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert ist und lastWillOnExit = true.</li>
+<li data-sourcepos="101:2-101:49">Nur wenn lastWillOnExitMsgStr nicht angegeben.</li>
+<li data-sourcepos="102:2-102:83">Wird als signed 64Bit-Wert binär beim normalen Beenden des Clients gepublished.</li>
+<li data-sourcepos="103:2-104:0">Default: Wenn weder lastWillOnExitMsgStr noch lastWillOnExitMsgInt angegeben sind, wird lastWillOnExitMsgStr auf lastWillMsgStr gesetzt, sofern dieser konfiguriert ist, ansonsten wird lastWillOnExitMsgInt auf lastWillMsgInt gesetzt.</li>
 </ul>
 </li>
-<li data-sourcepos="103:1-108:0">
-<p data-sourcepos="103:3-103:20"><strong>connectRetain:</strong></p>
-<ul data-sourcepos="104:2-108:0">
-<li data-sourcepos="104:2-104:12">Optional.</li>
-<li data-sourcepos="105:2-105:40">Nur wenn connectMessage konfiguriert.</li>
-<li data-sourcepos="106:2-106:43">Retained-Einstellung der Startnachricht.</li>
-<li data-sourcepos="107:2-108:0">Default: false.</li>
+<li data-sourcepos="105:1-108:0">
+<p data-sourcepos="105:3-105:20"><strong>connectMsgStr:</strong></p>
+<ul data-sourcepos="106:2-108:0">
+<li data-sourcepos="106:2-106:12">Optional.</li>
+<li data-sourcepos="107:2-108:0">Nachricht, die, wenn konfiguriert, beim Start des Clients gepublished wird.</li>
 </ul>
 </li>
-<li data-sourcepos="109:1-112:15">
-<p data-sourcepos="109:3-109:19"><strong>maxKeepAlive:</strong></p>
-<ul data-sourcepos="110:2-112:15">
+<li data-sourcepos="109:1-113:0">
+<p data-sourcepos="109:3-109:20"><strong>connectMsgInt:</strong></p>
+<ul data-sourcepos="110:2-113:0">
 <li data-sourcepos="110:2-110:12">Optional.</li>
-<li data-sourcepos="111:2-111:97">Maximales Zeitintervall in Sekunden, in dem der Broker Keep-Alive-Pakete an den Client sendet.</li>
-<li data-sourcepos="112:2-112:15">Default: 60.</li>
+<li data-sourcepos="111:2-111:42">Nur wenn connectMsgStr nicht angegeben.</li>
+<li data-sourcepos="112:2-113:0">Wenn angegeben, wird dieser Wert als signed 64Bit-Wert binär beim Start des Clients gepublished.</li>
+</ul>
+</li>
+<li data-sourcepos="114:1-119:0">
+<p data-sourcepos="114:3-114:19"><strong>connectTopic:</strong></p>
+<ul data-sourcepos="115:2-119:0">
+<li data-sourcepos="115:2-115:12">Optional.</li>
+<li data-sourcepos="116:2-116:58">Nur wenn connectMsgStr oder connectMsgInt konfiguriert.</li>
+<li data-sourcepos="117:2-117:68">Topic der Nachricht, die beim Start des Clients gepublished wird.</li>
+<li data-sourcepos="118:2-119:0">Default: lastWillTopic, wenn konfiguriert, sonst &quot;LWC&quot;.</li>
+</ul>
+</li>
+<li data-sourcepos="120:1-125:0">
+<p data-sourcepos="120:3-120:17"><strong>connectQos:</strong></p>
+<ul data-sourcepos="121:2-125:0">
+<li data-sourcepos="121:2-121:12">Optional.</li>
+<li data-sourcepos="122:2-122:58">Nur wenn connectMsgStr oder connectMsgInt konfiguriert.</li>
+<li data-sourcepos="123:2-123:41">Quality of Service der Startnachricht.</li>
+<li data-sourcepos="124:2-125:0">Default: defaultQos.</li>
+</ul>
+</li>
+<li data-sourcepos="126:1-131:0">
+<p data-sourcepos="126:3-126:20"><strong>connectRetain:</strong></p>
+<ul data-sourcepos="127:2-131:0">
+<li data-sourcepos="127:2-127:12">Optional.</li>
+<li data-sourcepos="128:2-128:58">Nur wenn connectMsgStr oder connectMsgInt konfiguriert.</li>
+<li data-sourcepos="129:2-129:43">Retained-Einstellung der Startnachricht.</li>
+<li data-sourcepos="130:2-131:0">Default: defaultRetain.</li>
+</ul>
+</li>
+<li data-sourcepos="132:1-135:15">
+<p data-sourcepos="132:3-132:19"><strong>maxKeepAlive:</strong></p>
+<ul data-sourcepos="133:2-135:15">
+<li data-sourcepos="133:2-133:12">Optional.</li>
+<li data-sourcepos="134:2-134:134">Maximales Zeitintervall in Sekunden, in dem der Broker Keep-Alive-Pakete an den Client sendet. Werte &lt; 10 werden auf 10 korrigiert.</li>
+<li data-sourcepos="135:2-135:15">Default: 60.</li>
 </ul>
 </li>
 </ul>

+ 44 - 21
svc/mqttcl/cfg/README.md

@@ -23,20 +23,26 @@
 * **devicePrefix:**
 	* Optional.
 	* Wird u. a. verwendet, um zusammen mit der SHM-UUID das Topic-Prefix zu generieren.
-	* Default: "GfA".
+	* Default: Leer, wenn nicht angegeben.
 
 * **deviceID:**
 	* Optional.
 	* Wird u. a. verwendet, um zusammen mit der SHM-UUID das Topic-Prefix zu generieren.
-	* Default: Automatisch generiert aus devicePrefix und MAC-Adresse.
+	* Default: Automatisch generiert aus devicePrefix und MAC-Adresse, oder nur MAC-Adresse, wenn kein devicePrefix angegeben.
+
+* **disableTopicPrefix:**
+	* Optional.
+	* Wenn true, wird kein Topic-Prefix gesendet.
+	* Default: false.
 
 * **topicPrefix:**
 	* Optional.
+	* Nur wenn disableTopicPrefix = false.
 	* Ersetzt, wenn angegeben, das Topic-Prefix.
 
 * **tlsMode:**
 	* Optional.
-	* 0 = kein TLS, 1 = TLS mit Zertifikat, 2 = TLS mit Preshared Key.
+	* 0 = kein TLS, 1 = TLS mit Zertifikat, 2 = TLS mit Preshared Key. Ungültige Werte werden auf 0 korrigiert!
 	* Default: 0 (kein TLS).
 
 * **tlsCaCrtFile, tlsClKeyFile, tlsClCrtFile:**
@@ -50,63 +56,80 @@
 	* Erforderlich wenn tlsMode = 2.
 	* Preshared Key als String im Hex-Format ohne führendes "0x".
 
-* **lastWillMessage:**
+* **lastWillMsgStr:**
 	* Optional.
 	* Wenn angegeben, wird diese Nachricht als "Last Will" gepublished.
 
+* **lastWillMsgInt:**
+	* Optional.
+	* Nur wenn lastWillMsgStr nicht angegeben.
+	* Wenn angegeben, wird dieser Wert als signed 64Bit-Wert binär als "Last Will" gepublished.
+
 * **lastWillTopic:**
 	* Optional.
-	* Nur wenn lastWillMessage konfiguriert.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.
 	* Topic des "Last Will".
-	* Default: "LAST_WILL_CONNECT".
+	* Default: "LWC".
 
 * **lastWillQos:**
 	* Optional.
-	* Nur wenn lastWillMessage konfiguriert.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.
 	* Quality of Service des "Last Will".
 	* Default: Wert des defaultQos.
 
 * **lastWillRetain:**
 	* Optional.
-	* Nur wenn lastWillMessage konfiguriert.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.
 	* Retained-Einstellung des "Last Will".
-	* Default: false.
+	* Default: defaultRetain.
 
 * **lastWillOnExit:**
 	* Optional.
-	* Nur wenn lastWillMessage konfiguriert.
-	* Wenn true, wird beim normalen Beenden des Clients eine "Last Will"-Message mit dem Wert von lastWillOnExitMsg gepublished.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert.
+	* Wenn true, wird auch beim normalen Beenden des Clients eine "Last Will"-Message mit dem Wert von lastWillOnExitMsgStr oder lastWillOnExitMsgInt gepublished.
 	* Default: true.
 
-* **lastWillOnExitMsg:**
+* **lastWillOnExitMsgStr:**
 	* Optional.
-	* Nur wenn lastWillMessage konfiguriert und lastWillOnExit = true.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert ist und lastWillOnExit = true.
 	* Nachricht, die beim	normalen Beenden des Clients gepublished wird.
-	* Default: lastWillMessage.
+	* Default: Wenn weder lastWillOnExitMsgStr noch lastWillOnExitMsgInt angegeben sind, wird lastWillOnExitMsgStr auf lastWillMsgStr gesetzt, sofern dieser konfiguriert ist, ansonsten wird lastWillOnExitMsgInt auf lastWillMsgInt gesetzt.
 
-* **connectMessage:**
+* **lastWillOnExitMsgInt:**
+	* Optional.
+	* Nur wenn lastWillMsgStr oder lastWillMsgInt konfiguriert ist und lastWillOnExit = true.
+	* Nur wenn lastWillOnExitMsgStr nicht angegeben.
+	* Wird als signed 64Bit-Wert binär beim normalen Beenden des Clients gepublished.
+	* Default: Wenn weder lastWillOnExitMsgStr noch lastWillOnExitMsgInt angegeben sind, wird lastWillOnExitMsgStr auf lastWillMsgStr gesetzt, sofern dieser konfiguriert ist, ansonsten wird lastWillOnExitMsgInt auf lastWillMsgInt gesetzt.
+
+* **connectMsgStr:**
 	* Optional.
 	* Nachricht, die, wenn konfiguriert, beim Start des Clients gepublished wird.
 
+* **connectMsgInt:**
+	* Optional.
+	* Nur wenn connectMsgStr nicht angegeben.
+	* Wenn angegeben, wird dieser Wert als signed 64Bit-Wert binär beim Start des Clients gepublished.
+
 * **connectTopic:**
 	* Optional.
-	* Nur wenn connectMessage konfiguriert.
+	* Nur wenn connectMsgStr oder connectMsgInt konfiguriert.
 	* Topic der Nachricht, die beim Start des Clients gepublished wird.
-	* Default: lastWillTopic, wenn konfiguriert, sonst "LAST_WILL_CONNECT".
+	* Default: lastWillTopic, wenn konfiguriert, sonst "LWC".
 
 * **connectQos:**
 	* Optional.
-	* Nur wenn connectMessage konfiguriert.
+	* Nur wenn connectMsgStr oder connectMsgInt konfiguriert.
 	* Quality of Service der Startnachricht.
 	* Default: defaultQos.
 
 * **connectRetain:**
 	* Optional.
-	* Nur wenn connectMessage konfiguriert.
+	* Nur wenn connectMsgStr oder connectMsgInt konfiguriert.
 	* Retained-Einstellung der Startnachricht.
-	* Default: false.
+	* Default: defaultRetain.
 
 * **maxKeepAlive:**
 	* Optional.
-	* Maximales Zeitintervall in Sekunden, in dem der Broker Keep-Alive-Pakete an den Client sendet.
+	* Maximales Zeitintervall in Sekunden, in dem der Broker Keep-Alive-Pakete an den Client sendet. Werte < 10 werden auf 10 korrigiert.
 	* Default: 60.

+ 10 - 10
svc/mqttcl/cfg/mqtt.conf.json

@@ -1,18 +1,18 @@
 {
-	"brokerAddr":		"server.addr",
+	"brokerAddr":		"192.168.0.106",
 	"brokerPort":		8883,
 	"defaultQos":		2,
 	"defaultRetain":	false,
-	"devicePrefix":		"OEM",
 	"tlsMode":			1,
-	"tlsCaCrtFile":		"/path/to/ca.crt",
-	"tlsClCrtFile":		"/path/to/client.crt",
-	"tlsClKeyFile":		"/path/to/client.key",
-	"lastWillTopic":	"LWC",
-	"lastWillMessage":	"X",
+	"tlsCaCrtFile":		"/opt/GfA/_OEM_/mqttcl/client/ca.crt",
+	"tlsClCrtFile":		"/opt/GfA/_OEM_/mqttcl/client/client.crt",
+	"tlsClKeyFile":		"/opt/GfA/_OEM_/mqttcl/client/client.key",
+	"lastWillMsgInt":	-1,
 	"lastWillRetain":	true,
 	"lastWillOnExit":	true,
-	"lastWillOnExitMsg": "E",
-	"connectMessage":	"C",
-	"connectRetain":	true
+	"lastWillOnExitMsgInt": 0,
+	"connectMsgInt":	1,
+	"connectRetain":	true,
+	"disableTopicPrefix": true,
+	"maxKeepAlive":		5
 }

+ 28 - 13
svc/mqttcl/main.cpp

@@ -271,7 +271,7 @@ static void _ProcessIncoming(CMqttClient &rcl, CMqttVarTable &vt, CMqttClConfig
 						switch((nType = jtVal.Type()))
 						{
 						case JSON_TRUE:
-							pVar->RemoveRetained(cfg.GetPrefix(), nullptr, rcl.GetMsgQueueSnd(), true);
+							pVar->RemoveRetained(cfg.GetTopicPrefix(), nullptr, rcl.GetMsgQueueSnd(), true);
 							break;
 						case JSON_FALSE:
 							g_lf.Warning("%s: command \"%s\":false has no effect!\n", pMsg->GetTopic().c_str(), _TOPIC_CTRL_KEY_REM_RETAINED);
@@ -611,6 +611,13 @@ static void _ProcessStateEvents(HAPPCTRL hAC, HAPPINFO hAI)
 	}
 }
 
+static std::string _GetTopicPrefixString(const CMqttClConfig &cfg)
+{
+	if(cfg.TopicPrefixDisabled())
+		return "";
+	return formatString("%s/", cfg.GetTopicPrefix());
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -730,18 +737,19 @@ int main(int /*argc*/, char **/*argv*/)
 
 		nTlsMode = cfg.GetTLSMode();
 //		TRACE("%s/%s\n", cfg.GetDeviceID(), cfg.GetShmID());
+		std::string strTopicPrefix = _GetTopicPrefixString(cfg);
 
 		////////////////////////////////////////////////////////////////////////////////////////////
 		// client control topic map
 
 		const SUB_CTRL_TOPIC subCtrlMap[] =
 		{
-			formatString("%s/%s/#", cfg.GetPrefix(), _TOPIC_CMD_CTRL),
-			formatString("%s/%s/%s/#", cfg.GetPrefix(), MQTT_TOPIC_VALUE_BINLE, _TOPIC_CMD_SET),
-			formatString("%s/%s/%s/#", cfg.GetPrefix(), MQTT_TOPIC_VALUE_BINBE, _TOPIC_CMD_SET),
-			formatString("%s/%s/%s/#", cfg.GetPrefix(), MQTT_TOPIC_VALUE_JSON, _TOPIC_CMD_SET),
-			formatString("%s/%s/%s/#", cfg.GetPrefix(), MQTT_TOPIC_VALUE_PBUF, _TOPIC_CMD_SET),
-//			formatString("%s/%s/#", cfg.GetPrefix(), _TOPIC_CMD_STATUS)
+			formatString("%s%s/#", strTopicPrefix.c_str(), _TOPIC_CMD_CTRL),
+			formatString("%s%s/%s/#", strTopicPrefix.c_str(), MQTT_TOPIC_VALUE_BINLE, _TOPIC_CMD_SET),
+			formatString("%s%s/%s/#", strTopicPrefix.c_str(), MQTT_TOPIC_VALUE_BINBE, _TOPIC_CMD_SET),
+			formatString("%s%s/%s/#", strTopicPrefix.c_str(), MQTT_TOPIC_VALUE_JSON, _TOPIC_CMD_SET),
+			formatString("%s%s/%s/#", strTopicPrefix.c_str(), MQTT_TOPIC_VALUE_PBUF, _TOPIC_CMD_SET),
+//			formatString("%s%s/#", strTopicPrefix.c_str(), _TOPIC_CMD_STATUS)
 		};
 
 		////////////////////////////////////////////////////////////////////////////////////////////
@@ -890,7 +898,7 @@ int main(int /*argc*/, char **/*argv*/)
 			case CLS_SetLastWill:
 				if(cfg.HasLastWill())
 				{
-					std::string strTopic = formatString("%s/%s", cfg.GetPrefix(), cfg.GetLastWillTopic());
+					std::string strTopic = formatString("%s%s", strTopicPrefix.c_str(), cfg.GetLastWillTopic());
 					if((nErr = mqttCl.will_set(strTopic.c_str(), cfg.GetLastWillMessageLength(), cfg.GetLastWillMessage(), cfg.GetLastWillQOS(), cfg.GetLastWillRetain())) != MOSQ_ERR_SUCCESS)
 					{
 						CMqttClient::EvalError(nErr, bReconnect, bConnPending, g_bIntr, strErr);
@@ -916,6 +924,8 @@ int main(int /*argc*/, char **/*argv*/)
 					g_cs = CLS_Connecting;
 				else if(!CMqttClient::EvalError(nErr, bReconnect, bConnPending, g_bIntr, strErr))
 				{
+					TRACE("CLS_Connect: %s\n", strErr.c_str());
+
 					if(bConnPending)
 						g_cs = CLS_Connecting;
 					else if(bReconnect)
@@ -948,6 +958,8 @@ int main(int /*argc*/, char **/*argv*/)
 					g_cs = CLS_Connecting;
 				else if(!CMqttClient::EvalError(nErr, bReconnect, bConnPending, g_bIntr, strErr))
 				{
+					TRACE("CLS_Reconnect: %s\n", strErr.c_str());
+
 					if(bConnPending)
 						g_cs = CLS_Connecting;
 					else if(bReconnect)
@@ -979,6 +991,8 @@ int main(int /*argc*/, char **/*argv*/)
 				g_nErrRetries = 0;
 				if(!mqttCl.TimedLoop(_NSEC_FROM_MSEC(_UPDATE_INTERVAL_MS), nErr, bReconnect, bConnPending, g_bIntr, strErr))
 				{
+					TRACE("CLS_Connecting: %s\n", strErr.c_str());
+
 					if(bReconnect)
 					{
 						g_csLast = g_cs;
@@ -1002,6 +1016,7 @@ int main(int /*argc*/, char **/*argv*/)
 				break;
 
 			case CLS_Connected:
+				TRACE("Connected to broker @ %s:%u.\n", cfg.GetBrokerAddr(), cfg.GetBrokerPort());
 				g_lf.Info("Connected to broker @ %s:%u.\n", cfg.GetBrokerAddr(), cfg.GetBrokerPort());
 				++nNumConn;
 				g_nSubcribed = 0;
@@ -1065,7 +1080,7 @@ int main(int /*argc*/, char **/*argv*/)
 			case CLS_PublishConnect:
 				if(cfg.HasConnectMsg())
 				{
-					std::string strTopic = formatString("%s/%s", cfg.GetPrefix(), cfg.GetConnectTopic());
+					std::string strTopic = formatString("%s%s", strTopicPrefix.c_str(), cfg.GetConnectTopic());
 					CMqttMessage *pMsg = CMqttMessage::CreateMessage(strTopic.c_str(), cfg.GetConnectMessage(), cfg.GetConnectMessageLength(), cfg.GetConnectQOS(), cfg.GetConnectRetain());
 					mqttCl.publish(pMsg);
 					pMsg->Release();
@@ -1097,7 +1112,7 @@ int main(int /*argc*/, char **/*argv*/)
 #endif	//	_TRACK_TIMES
 
 					_SIG_BLOCK(&g_set);
-					vtbl.CheckShmAndPublish(cfg.GetPrefix(), nullptr, mqttCl.GetMsgQueueSnd(), nLocked);
+					vtbl.CheckShmAndPublish(cfg.GetTopicPrefix(), nullptr, mqttCl.GetMsgQueueSnd(), nLocked);
 					_SIG_UNBLOCK(&g_set);
 #if _TRACK_TIMES
 					g_nDbgCounter2 = mqttCl.GetMsgQueueSnd().Size();
@@ -1145,7 +1160,7 @@ int main(int /*argc*/, char **/*argv*/)
 
 			case CLS_Err:
 				g_lf.Error("[%s] - %s\n", _GetClientStateString(g_csLast), strErr.c_str());
-				TRACE("Error: %s\n", strErr.c_str());
+				TRACE("[%s] - %s\n", _GetClientStateString(g_csLast), strErr.c_str());
 				g_fZombie = true;
 				g_cs = CLS_PublishDisconnect;
 				break;
@@ -1153,7 +1168,7 @@ int main(int /*argc*/, char **/*argv*/)
 			case CLS_PublishDisconnect:
 				if(cfg.HasLastWillOnExit())
 				{
-					std::string strTopic = formatString("%s/%s", cfg.GetPrefix(), cfg.GetLastWillTopic());
+					std::string strTopic = formatString("%s%s", strTopicPrefix.c_str(), cfg.GetLastWillTopic());
 					CMqttMessage *pMsg = CMqttMessage::CreateMessage(strTopic.c_str(), cfg.GetLastWillOnExitMessage(), cfg.GetLastWillOnExitMessageLength(), cfg.GetLastWillQOS(), cfg.GetLastWillRetain());
 					mqttCl.publish(pMsg);
 					pMsg->Release();
@@ -1197,7 +1212,7 @@ int main(int /*argc*/, char **/*argv*/)
 				break;
 
 			case CLS_Cleanup:
-				g_lf.Info("Clean up.\n");
+				g_lf.Info("Mqtt clean up.\n");
 				CMqttClient::Cleanup();
 				if((g_fPauseImp || g_fPauseCmd) && !g_bIntr)
 					g_cs = CLS_Paused;

+ 3 - 0
svc/rest/html/index.html

@@ -7,6 +7,9 @@
 
 <body>
 	<h1 style="text-align:center;">REST-Service auf Sitara</h1>
+	<div style="text-align:center;">
+		<img src="/plugin/svgtest" alt="SVG from Plugin" title="SVG from Plugin" />
+	</div>
 </body>
 
 </html>

+ 17 - 6
svc/rest/main.cpp

@@ -43,6 +43,16 @@ static void _SigHandler(int sig)
 	g_fRun = g_fPauseImp = g_fPauseCmd = g_fZombie = false;
 }
 
+static void _LockSHM(HSHM hShm)
+{
+	::GfaIpcLockSHMAndSigBlock(hShm, &g_set);
+}
+
+static void _UnlockSHM(HSHM hShm)
+{
+	::GfaIpcUnlockSHMAndSigUnblock(hShm, &g_set);
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI)
@@ -283,11 +293,12 @@ int main(int argc, char *argv[])
 		srp.pMap	= &map;
 		srp.pszUuid	= UUID_SHM;
 
-		REST_PLUGIN_REQUEST_HANDLER_PARAMS hp;
-		hp.hShm = hShm;
-		hp.pShm = pShm;
-		hp.pParam = reinterpret_cast<void*>(&shm);
-		_uuid_parse(UUID_SHM, &hp.uuidShm);
+		REST_PLUGIN_REQUEST_CONTEXT rprc;
+		rprc.hShm = hShm;
+		rprc.pShm = pShm;
+		rprc.pfnLockSHM = _LockSHM;
+		rprc.pfnUnlockSHM = _UnlockSHM;
+		_uuid_parse(UUID_SHM, &rprc.uuidShm);
 
 		/////////////////////////////////////////////////////////////////////
 		/////////////////////////////////////////////////////////////////////
@@ -300,7 +311,7 @@ int main(int argc, char *argv[])
 			break;
 		}
 
-		if(LoadPlugins(pszRootDir, &instance, jerr, &hp) < 0)
+		if(LoadPlugins(pszRootDir, &instance, jerr, &rprc) < 0)
 		{
 			ETRACE("LoadPlugins failed!\n");
 			nRet = -1;