diff --git a/apps/0BUILD b/apps/0BUILD
index 56a73bd..e97532b 100644
--- a/apps/0BUILD
+++ b/apps/0BUILD
@@ -7,6 +7,7 @@
aqhome-mqttlog
aqhome-data
aqhome-nodes
+ aqhome-react
diff --git a/apps/aqhome-react/0BUILD b/apps/aqhome-react/0BUILD
new file mode 100644
index 0000000..a32b4e2
--- /dev/null
+++ b/apps/aqhome-react/0BUILD
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+ $(gwenhywfar_cflags)
+ -I$(topsrcdir)
+ -I$(topbuilddir)
+ -I$(topsrcdir)/apps
+ -I$(topbuilddir)/apps
+ -I$(builddir)
+ -I$(srcdir)
+
+
+
+ --include=$(builddir)
+ --include=$(srcdir)
+
+
+ $(visibility_cflags)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(local/typefiles)
+ main.c
+
+
+
+ aqhome
+ aqhreact_types
+
+
+
+ $(gwenhywfar_libs)
+
+
+
+ types
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/aqhome-react/aqhome_react.h b/apps/aqhome-react/aqhome_react.h
new file mode 100644
index 0000000..fe4e6bb
--- /dev/null
+++ b/apps/aqhome-react/aqhome_react.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_H
+#define AQHOME_REACT_H
+
+
+#include
+
+
+#define AQHOME_REACT_DEFAULT_PIDFILE "/var/run/aqhome-react.pid"
+#define AQHOME_REACT_DEFAULT_DATADIR "/var/lib/aqhome-react"
+
+#define AQHOME_REACT_DEFAULT_BROKER_PORT 1899
+#define AQHOME_REACT_DEFAULT_BROKER_CLIENTID "react"
+
+
+
+
+struct AQHOME_REACT {
+ GWEN_MSG_ENDPOINT *rootEndpoint;
+ GWEN_MSG_ENDPOINT *brokerEndpoint; /* do not free (is part of tree pointed to by rootEndpoint) */
+
+ GWEN_DB_NODE *dbArgs;
+ char *pidFile;
+ int timeout; /* timeout for run e.g. inside valgrind */
+
+};
+
+
+#endif
+
diff --git a/apps/aqhome-react/aqhome_react_p.h b/apps/aqhome-react/aqhome_react_p.h
new file mode 100644
index 0000000..3b3d38c
--- /dev/null
+++ b/apps/aqhome-react/aqhome_react_p.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_P_H
+#define AQHOME_REACT_P_H
+
+
+#include "./aqhome_react.h"
+
+
+#define AQHOME_REACT_DEFAULT_PIDFILE "/var/run/aqhome-react.pid"
+#define AQHOME_REACT_DEFAULT_DATADIR "/var/lib/aqhome-react"
+
+#define AQHOME_REACT_DEFAULT_BROKER_PORT 1899
+#define AQHOME_REACT_DEFAULT_BROKER_CLIENTID "react"
+
+
+
+
+struct AQHOME_REACT {
+ GWEN_MSG_ENDPOINT *rootEndpoint;
+ GWEN_MSG_ENDPOINT *brokerEndpoint; /* do not free (is part of tree pointed to by rootEndpoint) */
+
+ GWEN_DB_NODE *dbArgs;
+ char *pidFile;
+ int timeout; /* timeout for run e.g. inside valgrind */
+
+ AQH_STORAGE *storage;
+
+};
+
+
+#endif
+
diff --git a/apps/aqhome-react/main.c b/apps/aqhome-react/main.c
new file mode 100644
index 0000000..bf6f278
--- /dev/null
+++ b/apps/aqhome-react/main.c
@@ -0,0 +1,9 @@
+
+
+
+
+int main(int argc, char **argv)
+{
+}
+
+
diff --git a/apps/aqhome-react/types/0BUILD b/apps/aqhome-react/types/0BUILD
new file mode 100644
index 0000000..e777361
--- /dev/null
+++ b/apps/aqhome-react/types/0BUILD
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+ $(gwenhywfar_cflags)
+ -I$(topsrcdir)
+ -I$(topbuilddir)
+ -I$(topsrcdir)/apps
+ -I$(topbuilddir)/apps
+ -I$(builddir)
+ -I$(srcdir)
+
+
+
+ --include=$(builddir)
+ --include=$(srcdir)
+
+
+ $(visibility_cflags)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ dataobject.h
+ dataobject_p.h
+ inputslot.h
+ inputslot_p.h
+
+
+
+ $(local/typefiles)
+ dataobject.c
+ inputslot.c
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/aqhome-react/types/dataobject.c b/apps/aqhome-react/types/dataobject.c
new file mode 100644
index 0000000..628112d
--- /dev/null
+++ b/apps/aqhome-react/types/dataobject.c
@@ -0,0 +1,193 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2024 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+
+#include "./dataobject_p.h"
+
+#include
+#include
+
+
+
+GWEN_LIST_FUNCTIONS(AQHREACT_DATAOBJECT, AQHREACT_DataObject)
+
+
+
+
+AQHREACT_DATAOBJECT *AQHREACT_DataObject_new()
+{
+ AQHREACT_DATAOBJECT *dataObject;
+
+ GWEN_NEW_OBJECT(AQHREACT_DATAOBJECT, dataObject);
+ dataObject->_refCount=1;
+ GWEN_LIST_INIT(AQHREACT_DATAOBJECT, dataObject);
+ return dataObject;
+}
+
+
+
+void AQHREACT_DataObject_free(AQHREACT_DATAOBJECT *dataObject)
+{
+ if (dataObject) {
+ if (dataObject->_refCount==1) {
+ GWEN_LIST_FINI(AQHREACT_DATAOBJECT, dataObject);
+ free(dataObject->systemValueId);
+ free(dataObject->valueUnits);
+ free(dataObject->stringData);
+ dataObject->_refCount=0;
+ GWEN_FREE_OBJECT(dataObject);
+ }
+ else if (dataObject->_refCount<1) {
+ DBG_ERROR(NULL, "dataobject already freed!");
+ }
+ else
+ dataObject->_refCount--;
+ }
+}
+
+
+
+AQHREACT_DATAOBJECT *AQHREACT_DataObject_dup(const AQHREACT_DATAOBJECT *origObject)
+{
+ if (origObject) {
+ AQHREACT_DATAOBJECT *dataObject;
+
+ dataObject=AQHREACT_DataObject_new();
+ dataObject->valueId=origObject->valueId;
+ AQHREACT_DataObject_SetSystemValueId(dataObject, origObject->systemValueId);
+ AQHREACT_DataObject_SetValueUnits(dataObject, origObject->valueUnits);
+ dataObject->timestamp=origObject->timestamp;
+ dataObject->dataType=origObject->dataType;
+ dataObject->doubleData=origObject->doubleData;
+ AQHREACT_DataObject_SetStringData(dataObject, origObject->stringData);
+ return dataObject;
+ }
+ else
+ return NULL;
+}
+
+
+
+uint64_t AQHREACT_DataObject_GetValueId(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->valueId):0;
+}
+
+
+
+void AQHREACT_DataObject_SetValueId(AQHREACT_DATAOBJECT *dataObject, uint64_t i)
+{
+ if (dataObject)
+ dataObject->valueId=i;
+}
+
+
+
+const char *AQHREACT_DataObject_GetSystemValueId(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->systemValueId):NULL;
+}
+
+
+
+void AQHREACT_DataObject_SetSystemValueId(AQHREACT_DATAOBJECT *dataObject, const char *s)
+{
+ if (dataObject) {
+ free(dataObject->systemValueId);
+ dataObject->systemValueId=(s && *s)?strdup(s):NULL;
+ }
+}
+
+
+
+const char *AQHREACT_DataObject_GetValueUnits(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->valueUnits):NULL;
+}
+
+
+
+void AQHREACT_DataObject_SetValueUnits(AQHREACT_DATAOBJECT *dataObject, const char *s)
+{
+ if (dataObject) {
+ free(dataObject->valueUnits);
+ dataObject->valueUnits=(s && *s)?strdup(s):NULL;
+ }
+}
+
+
+
+uint64_t AQHREACT_DataObject_GetTimestamp(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->timestamp):0;
+}
+
+
+
+void AQHREACT_DataObject_SetTimestamp(AQHREACT_DATAOBJECT *dataObject, uint64_t i)
+{
+ if (dataObject)
+ dataObject->timestamp=i;
+}
+
+
+
+int AQHREACT_DataObject_GetDataType(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->dataType):AQHREACT_DATAOBJECTTYPE_UNKNOWN;
+}
+
+
+
+void AQHREACT_DataObject_SetDataType(AQHREACT_DATAOBJECT *dataObject, int i)
+{
+ if (dataObject)
+ dataObject->dataType=i;
+}
+
+
+
+double AQHREACT_DataObject_GetDoubleData(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->doubleData):0.0;
+}
+
+
+
+void AQHREACT_DataObject_SetDoubleData(AQHREACT_DATAOBJECT *dataObject, double i)
+{
+ if (dataObject)
+ dataObject->doubleData=i;
+}
+
+
+
+const char *AQHREACT_DataObject_GetStringData(const AQHREACT_DATAOBJECT *dataObject)
+{
+ return dataObject?(dataObject->stringData):NULL;
+}
+
+
+
+void AQHREACT_DataObject_SetStringData(AQHREACT_DATAOBJECT *dataObject, const char *s)
+{
+ if (dataObject) {
+ free(dataObject->stringData);
+ dataObject->stringData=(s && *s)?strdup(s):NULL;
+ }
+}
+
+
+
+
+
+
diff --git a/apps/aqhome-react/types/dataobject.h b/apps/aqhome-react/types/dataobject.h
new file mode 100644
index 0000000..ce7b2c7
--- /dev/null
+++ b/apps/aqhome-react/types/dataobject.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_DATAOBJECT_H
+#define AQHOME_REACT_DATAOBJECT_H
+
+
+#include "aqhome-react/aqhome_react.h"
+
+#include
+
+
+typedef struct AQHREACT_DATAOBJECT AQHREACT_DATAOBJECT;
+GWEN_LIST_FUNCTION_DEFS(AQHREACT_DATAOBJECT, AQHREACT_DataObject)
+
+
+enum {
+ AQHREACT_DATAOBJECTTYPE_UNKNOWN=0,
+ AQHREACT_DATAOBJECTTYPE_DOUBLE,
+ AQHREACT_DATAOBJECTTYPE_STRING
+};
+
+
+
+AQHREACT_DATAOBJECT *AQHREACT_DataObject_new();
+void AQHREACT_DataObject_free(AQHREACT_DATAOBJECT *dataObject);
+AQHREACT_DATAOBJECT *AQHREACT_DataObject_dup(const AQHREACT_DATAOBJECT *origObject);
+
+
+uint64_t AQHREACT_DataObject_GetValueId(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetValueId(AQHREACT_DATAOBJECT *dataObject, uint64_t i);
+
+const char *AQHREACT_DataObject_GetSystemValueId(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetSystemValueId(AQHREACT_DATAOBJECT *dataObject, const char *s);
+
+const char *AQHREACT_DataObject_GetValueUnits(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetValueUnits(AQHREACT_DATAOBJECT *dataObject, const char *s);
+
+uint64_t AQHREACT_DataObject_GetTimestamp(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetTimestamp(AQHREACT_DATAOBJECT *dataObject, uint64_t i);
+
+int AQHREACT_DataObject_GetDataType(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetDataType(AQHREACT_DATAOBJECT *dataObject, int i);
+
+
+double AQHREACT_DataObject_GetDoubleData(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetDoubleData(AQHREACT_DATAOBJECT *dataObject, double i);
+
+const char *AQHREACT_DataObject_GetStringData(const AQHREACT_DATAOBJECT *dataObject);
+void AQHREACT_DataObject_SetStringData(AQHREACT_DATAOBJECT *dataObject, const char *s);
+
+
+#endif
+
diff --git a/apps/aqhome-react/types/dataobject_p.h b/apps/aqhome-react/types/dataobject_p.h
new file mode 100644
index 0000000..0f1e906
--- /dev/null
+++ b/apps/aqhome-react/types/dataobject_p.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_DATAOBJECT_P_H
+#define AQHOME_REACT_DATAOBJECT_P_H
+
+
+#include "aqhome-react/types/dataobject.h"
+
+
+struct AQHREACT_DATAOBJECT {
+ GWEN_LIST_ELEMENT(AQHREACT_DATAOBJECT)
+
+ int _refCount;
+ uint64_t valueId;
+ char *systemValueId;
+ char *valueUnits;
+ uint64_t timestamp;
+ int dataType;
+ double doubleData;
+ char *stringData;
+};
+
+
+#endif
+
diff --git a/apps/aqhome-react/types/inputslot.c b/apps/aqhome-react/types/inputslot.c
new file mode 100644
index 0000000..dc03c25
--- /dev/null
+++ b/apps/aqhome-react/types/inputslot.c
@@ -0,0 +1,145 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2024 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+
+#include "./inputslot_p.h"
+
+#include
+#include
+
+
+
+
+AQHREACT_INPUT_SLOT *AQHREACT_InputSlot_new()
+{
+ AQHREACT_INPUT_SLOT *inSlot;
+
+ GWEN_NEW_OBJECT(AQHREACT_INPUT_SLOT, inSlot);
+ return inSlot;
+}
+
+
+
+void AQHREACT_InputSlot_free(AQHREACT_INPUT_SLOT *inSlot)
+{
+ if (inSlot) {
+ free(inSlot->name);
+ free(inSlot->description);
+ AQHREACT_DataObject_free(inSlot->currentDataObject);
+ GWEN_FREE_OBJECT(inSlot);
+ }
+}
+
+
+
+const char *AQHREACT_InputSlot_GetName(const AQHREACT_INPUT_SLOT *inSlot)
+{
+ return inSlot?inSlot->name:NULL;
+}
+
+
+
+void AQHREACT_InputSlot_SetName(AQHREACT_INPUT_SLOT *inSlot, const char *s)
+{
+ if (inSlot) {
+ free(inSlot->name);
+ inSlot->name=s?strdup(s):NULL;
+ }
+}
+
+
+
+const char *AQHREACT_InputSlot_GetDescription(const AQHREACT_INPUT_SLOT *inSlot)
+{
+ return inSlot?inSlot->description:NULL;
+}
+
+
+
+void AQHREACT_InputSlot_SetDescription(AQHREACT_INPUT_SLOT *inSlot, const char *s)
+{
+ if (inSlot) {
+ free(inSlot->description);
+ inSlot->description=s?strdup(s):NULL;
+ }
+}
+
+
+
+uint32_t AQHREACT_InputSlot_GetFlags(const AQHREACT_INPUT_SLOT *inSlot)
+{
+ return inSlot?inSlot->flags:0;
+}
+
+
+
+void AQHREACT_InputSlot_SetFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i)
+{
+ if (inSlot)
+ inSlot->flags=i;
+}
+
+
+
+void AQHREACT_InputSlot_AddFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i)
+{
+ if (inSlot)
+ inSlot->flags|=i;
+}
+
+
+
+void AQHREACT_InputSlot_SubFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i)
+{
+ if (inSlot)
+ inSlot->flags&=~i;
+}
+
+
+
+int AQHREACT_InputSlot_GetAcceptedDataType(const AQHREACT_INPUT_SLOT *inSlot)
+{
+ return inSlot?inSlot->acceptedDataType:AQHREACT_DATAOBJECTTYPE_UNKNOWN;
+}
+
+
+
+void AQHREACT_InputSlot_SetAcceptedDataType(AQHREACT_INPUT_SLOT *inSlot, int i)
+{
+ if (inSlot)
+ inSlot->acceptedDataType=i;
+}
+
+
+
+AQHREACT_DATAOBJECT *AQHREACT_InputSlot_GetCurrentDataObject(const AQHREACT_INPUT_SLOT *inSlot)
+{
+ return inSlot?inSlot->currentDataObject:NULL;
+}
+
+
+
+void AQHREACT_InputSlot_SetCurrentDataObject(AQHREACT_INPUT_SLOT *inSlot, AQHREACT_DATAOBJECT *dataObject)
+{
+ if (inSlot) {
+ AQHREACT_DataObject_free(inSlot->currentDataObject);
+ inSlot->currentDataObject=dataObject;
+ }
+}
+
+
+
+
+
+
+
+
diff --git a/apps/aqhome-react/types/inputslot.h b/apps/aqhome-react/types/inputslot.h
new file mode 100644
index 0000000..ce44fdc
--- /dev/null
+++ b/apps/aqhome-react/types/inputslot.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2024 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_INPUTSLOT_H
+#define AQHOME_REACT_INPUTSLOT_H
+
+
+#include "aqhome-react/aqhome_react.h"
+
+typedef struct AQHREACT_INPUT_SLOT AQHREACT_INPUT_SLOT;
+
+
+#include "aqhome-react/types/dataobject.h"
+
+
+AQHREACT_INPUT_SLOT *AQHREACT_InputSlot_new();
+void AQHREACT_InputSlot_free(AQHREACT_INPUT_SLOT *inSlot);
+
+const char *AQHREACT_InputSlot_GetName(const AQHREACT_INPUT_SLOT *inSlot);
+void AQHREACT_InputSlot_SetName(AQHREACT_INPUT_SLOT *inSlot, const char *s);
+
+const char *AQHREACT_InputSlot_GetDescription(const AQHREACT_INPUT_SLOT *inSlot);
+void AQHREACT_InputSlot_SetDescription(AQHREACT_INPUT_SLOT *inSlot, const char *s);
+
+uint32_t AQHREACT_InputSlot_GetFlags(const AQHREACT_INPUT_SLOT *inSlot);
+void AQHREACT_InputSlot_SetFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i);
+void AQHREACT_InputSlot_AddFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i);
+void AQHREACT_InputSlot_SubFlags(AQHREACT_INPUT_SLOT *inSlot, uint32_t i);
+
+int AQHREACT_InputSlot_GetAcceptedDataType(const AQHREACT_INPUT_SLOT *inSlot);
+void AQHREACT_InputSlot_SetAcceptedDataType(AQHREACT_INPUT_SLOT *inSlot, int i);
+
+AQHREACT_DATAOBJECT *AQHREACT_InputSlot_GetCurrentDataObject(const AQHREACT_INPUT_SLOT *inSlot);
+void AQHREACT_InputSlot_SetCurrentDataObject(AQHREACT_INPUT_SLOT *inSlot, AQHREACT_DATAOBJECT *dataObject);
+
+
+
+
+#endif
+
diff --git a/apps/aqhome-react/types/inputslot_p.h b/apps/aqhome-react/types/inputslot_p.h
new file mode 100644
index 0000000..6a19baa
--- /dev/null
+++ b/apps/aqhome-react/types/inputslot_p.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2024 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQHOME_REACT_INPUTSLOT_P_H
+#define AQHOME_REACT_INPUTSLOT_P_H
+
+
+#include "aqhome-react/types/inputslot.h"
+
+
+struct AQHREACT_INPUT_SLOT {
+ char *name;
+ char *description;
+ uint32_t flags;
+ int acceptedDataType;
+ AQHREACT_DATAOBJECT *currentDataObject;
+};
+
+
+#endif
+