diff --git a/apps/aqhome-data/0BUILD b/apps/aqhome-data/0BUILD
index 3a818c7..46d9adf 100644
--- a/apps/aqhome-data/0BUILD
+++ b/apps/aqhome-data/0BUILD
@@ -46,6 +46,7 @@
c_getdatapoints.h
c_getlastdatapoint.h
c_setdata.h
+ c_addvalue.h
@@ -61,6 +62,7 @@
c_getdatapoints.c
c_getlastdatapoint.c
c_setdata.c
+ c_addvalue.c
main.c
diff --git a/apps/aqhome-data/c_addvalue.c b/apps/aqhome-data/c_addvalue.c
new file mode 100644
index 0000000..9c62122
--- /dev/null
+++ b/apps/aqhome-data/c_addvalue.c
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * 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.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+
+#include "./c_addvalue.h"
+#include "./aqhome_data_p.h"
+#include "./loop.h"
+#include "aqhome/ipc/data/ipc_data.h"
+#include "aqhome/ipc/endpoint_ipc.h"
+#include "aqhome/ipc/msg_ipc_result.h"
+#include "aqhome/ipc/data/msg_data_addvalue.h"
+#include "aqhome/ipc/msg_ipc_tag16.h"
+
+#include
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * defines
+ * ------------------------------------------------------------------------------------------------
+ */
+
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * forward declarations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * implementations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg)
+{
+ GWEN_MSG *outMsg;
+ int resultCode=AQH_MSG_IPC_SUCCESS;
+ GWEN_TAG16_LIST *tagList;
+ AQH_VALUE *value;
+ char *valueName=NULL;
+ char *valueUnits=NULL;
+ int valueType;
+
+ tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_UNITS);
+ valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_TYPE);
+ valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0;
+ }
+
+ value=AqHomeData_GetOrCreateValueForDriver(aqh, ep, valueName, valueUnits, valueType);
+ if (value==NULL)
+ resultCode=AQH_MSG_IPC_ERROR_PERMS;
+ free(valueUnits);
+ free(valueName);
+
+ outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode);
+ GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
+}
+
+
+
diff --git a/apps/aqhome-data/c_addvalue.h b/apps/aqhome-data/c_addvalue.h
new file mode 100644
index 0000000..7587902
--- /dev/null
+++ b/apps/aqhome-data/c_addvalue.h
@@ -0,0 +1,25 @@
+/****************************************************************************
+ * 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_DATA_C_ADDVALUE_H
+#define AQHOME_DATA_C_ADDVALUE_H
+
+
+#include "./aqhome_data.h"
+
+
+void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg);
+
+
+
+#endif
+
+
+
+
+
diff --git a/apps/aqhome-data/c_getdatapoints.c b/apps/aqhome-data/c_getdatapoints.c
index a862e8d..8963f49 100644
--- a/apps/aqhome-data/c_getdatapoints.c
+++ b/apps/aqhome-data/c_getdatapoints.c
@@ -15,8 +15,10 @@
#include "./aqhome_data_p.h"
#include "aqhome/ipc/data/ipc_data.h"
#include "aqhome/ipc/data/msg_data_datapoints.h"
+#include "aqhome/ipc/data/msg_data_getdata.h"
#include "aqhome/ipc/endpoint_ipc.h"
#include "aqhome/ipc/msg_ipc_result.h"
+#include "aqhome/ipc/msg_ipc_tag16.h"
#include
@@ -36,6 +38,8 @@
* ------------------------------------------------------------------------------------------------
*/
+static int _getAndSendDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd);
+
/* ------------------------------------------------------------------------------------------------
@@ -47,77 +51,84 @@
void AqHomeData_HandleGetDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *recvdMsg)
{
GWEN_MSG *outMsg;
- int resultCode=0;
+ int resultCode=AQH_MSG_IPC_SUCCESS;
if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_READDATA) {
- if (AQH_DataPointsDataIpcMsg_IsValid(recvdMsg)) {
- const char *valueName;
+ GWEN_TAG16_LIST *tagList;
+ AQH_VALUE *value;
+ char *valueName=NULL;
+ uint64_t tsBegin=0;
+ uint64_t tsEnd=0;
- valueName=AQH_DataPointsDataIpcMsg_GetValueName(recvdMsg);
- if (valueName) {
- const AQH_VALUE *value;
+ tagList=AQH_Tag16IpcMsg_ParseTags(recvdMsg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
- value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
- if (value) {
- uint64_t valueId;
- uint32_t numValues;
- uint64_t tsBegin=0;
- uint64_t tsEnd=0;
- uint64_t *tablePtr;
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
- valueId=AQH_Value_GetId(value);
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN);
+ tsBegin=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
- numValues=AQH_DataPointsDataIpcMsg_GetNumValues(recvdMsg);
- if (numValues==1) {
- const uint64_t *dataPoints;
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_END);
+ tsEnd=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+ }
- dataPoints=AQH_DataPointsDataIpcMsg_GetDataPoints(recvdMsg);
- tsBegin=dataPoints[0];
- tsEnd=dataPoints[1];
- }
-
- tablePtr=AQH_Storage_GetDataPoints(aqh->storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
- if (tablePtr) {
- int numTableEntries;
- int numDataPoints;
-
- numTableEntries=(int)(tablePtr[0]);
- numDataPoints=numTableEntries/2;
- outMsg=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP, AQH_MSGDATA_DATAPOINTS_FLAGS_LASTMSG,
- valueId,
- AQH_Value_GetNameForSystem(value),
- AQH_Value_GetValueUnits(value),
- &(tablePtr[1]), numDataPoints);
- GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
- free(tablePtr);
- return;
- }
- else {
- DBG_INFO(NULL, "No matching datapoints for value \"%s\"", valueName);
- resultCode=AQH_MSG_IPC_ERROR_NODATA;
- }
- }
- else {
- DBG_INFO(NULL, "Value \"%s\" not found", valueName);
- resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
- }
- }
- else {
- DBG_INFO(NULL, "No value name in request");
- resultCode=AQH_MSG_IPC_ERROR_INVALID;
- }
+ value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
+ if (value) {
+ resultCode=_getAndSendDataPoints(aqh, ep, value, tsBegin, tsEnd);
+ if (resultCode==AQH_MSG_IPC_SUCCESS)
+ return;
}
else {
- DBG_INFO(NULL, "Invalid request message");
- resultCode=AQH_MSG_IPC_ERROR_INVALID;
+ DBG_INFO(NULL, "Value \"%s\" does not exist", valueName);
+ resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
}
+ free(valueName);
}
else {
DBG_ERROR(AQH_LOGDOMAIN, "No permissions to read data");
resultCode=AQH_MSG_IPC_ERROR_PERMS;
}
+
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode);
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
}
+
+int _getAndSendDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd)
+{
+ uint64_t valueId;
+ uint64_t *tablePtr;
+
+ valueId=AQH_Value_GetId(value);
+
+ tablePtr=AQH_Storage_GetDataPoints(aqh->storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
+ if (tablePtr) {
+ int numTableEntries;
+ int numDataPoints;
+ GWEN_MSG *outMsg;
+
+ numTableEntries=(int)(tablePtr[0]);
+ numDataPoints=numTableEntries/2;
+ outMsg=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP, AQH_MSGDATA_DATAPOINTS_FLAGS_LASTMSG,
+ valueId,
+ AQH_Value_GetNameForSystem(value),
+ AQH_Value_GetValueUnits(value),
+ &(tablePtr[1]), numDataPoints);
+ GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
+ free(tablePtr);
+ return AQH_MSG_IPC_SUCCESS;
+ }
+ else {
+ DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
+ return AQH_MSG_IPC_ERROR_NODATA;
+ }
+}
+
+
+
+
+
+
diff --git a/apps/aqhome-data/c_setdata.c b/apps/aqhome-data/c_setdata.c
index b67f434..2700718 100644
--- a/apps/aqhome-data/c_setdata.c
+++ b/apps/aqhome-data/c_setdata.c
@@ -13,10 +13,12 @@
#include "./c_setdata.h"
#include "./aqhome_data_p.h"
+#include "./loop.h"
#include "aqhome/ipc/data/ipc_data.h"
-#include "aqhome/ipc/data/msg_data_datapoints.h"
+#include "aqhome/ipc/data/msg_data_singledata.h"
#include "aqhome/ipc/endpoint_ipc.h"
#include "aqhome/ipc/msg_ipc_result.h"
+#include "aqhome/ipc/msg_ipc_tag16.h"
#include
@@ -35,6 +37,8 @@
* ------------------------------------------------------------------------------------------------
*/
+static int _forwardDataToDriver(AQHOME_DATA *aqh, const AQH_VALUE *v, uint64_t timestamp, double datapoint);
+
/* ------------------------------------------------------------------------------------------------
@@ -42,89 +46,83 @@
* ------------------------------------------------------------------------------------------------
*/
-void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *recvdMsg)
+void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const GWEN_MSG *recvdMsg)
{
GWEN_MSG *outMsg;
int resultCode=AQH_MSG_IPC_SUCCESS;
+ GWEN_TAG16_LIST *tagList;
+ AQH_VALUE *value;
+ char *valueName=NULL;
+ uint64_t timestamp=0;
+ union {double f; uint64_t i;} u;
- if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_SETDATA) {
- if (AQH_DataPointsDataIpcMsg_IsValid(recvdMsg)) {
- uint32_t numValues;
-
- numValues=AQH_DataPointsDataIpcMsg_GetNumValues(recvdMsg);
- if (numValues==1) {
- const char *s;
-
- s=AQH_DataPointsDataIpcMsg_GetValueName(recvdMsg);
- if (s && *s) {
- AQH_VALUE *v;
-
- v=AQH_Storage_GetValueByNameForSystem(aqh->storage, s);
- if (v==NULL) {
- resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
- }
- else {
- const uint64_t *dataPoints;
-
- dataPoints=AQH_DataPointsDataIpcMsg_GetDataPoints(recvdMsg);
- if (dataPoints) {
- const char *driverName;
+ tagList=AQH_Tag16IpcMsg_ParseTags(recvdMsg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
- driverName=AQH_Value_GetDriver(v);
- if (driverName && *driverName) {
- GWEN_MSG_ENDPOINT *ep;
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
- ep=AqHomeData_GetIpcEndpointByServiceName(aqh, driverName);
- if (ep) {
- GWEN_MSG *driverMsg;
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_TIME);
+ timestamp=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
- DBG_INFO(AQH_LOGDOMAIN, "Sending SETDATA msg to driver endpoint (%s)", GWEN_MsgEndpoint_GetName(ep));
- driverMsg=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA,
- 0, /* flags */
- AQH_Value_GetId(v),
- AQH_Value_GetNameForDriver(v),
- AQH_Value_GetValueUnits(v),
- dataPoints, numValues);
- GWEN_MsgEndpoint_AddSendMessage(ep, driverMsg);
- }
- else {
- DBG_INFO(NULL, "Driver \"%s\" not available", driverName);
- resultCode=AQH_MSG_IPC_ERROR_GENERIC;
- }
- }
- else {
- DBG_INFO(NULL, "No driver name");
- resultCode=AQH_MSG_IPC_ERROR_GENERIC;
- }
- }
- else {
- DBG_INFO(NULL, "No datapoints");
- resultCode=AQH_MSG_IPC_ERROR_BADDATA;
- }
- }
- }
- else {
- DBG_INFO(NULL, "Value without name ");
- resultCode=AQH_MSG_IPC_ERROR_INVALID;
- }
- }
- else {
- DBG_INFO(NULL, "Invalid number of datapoints");
- resultCode=AQH_MSG_IPC_ERROR_BADDATA;
- }
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_DATA);
+ u.i=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+ }
+
+ value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
+ if (value) {
+ if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
+ resultCode=_forwardDataToDriver(aqh, value, timestamp, u.f);
}
else {
- DBG_INFO(NULL, "Invalid message received");
- resultCode=AQH_MSG_IPC_ERROR_BADDATA;
+ DBG_INFO(NULL, "Value \"%s\" is not an actor", valueName);
+ resultCode=AQH_MSG_IPC_ERROR_INVALID;
}
}
else {
- DBG_ERROR(AQH_LOGDOMAIN, "No permissions to set data");
- resultCode=AQH_MSG_IPC_ERROR_PERMS;
+ DBG_INFO(NULL, "Actor value \"%s\" does not exist", valueName);
+ resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
}
+ free(valueName);
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode);
- GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
+ GWEN_MsgEndpoint_AddSendMessage(epSrc, outMsg);
+}
+
+
+
+int _forwardDataToDriver(AQHOME_DATA *aqh, const AQH_VALUE *v, uint64_t timestamp, double datapoint)
+{
+ const char *driverName;
+
+ driverName=AQH_Value_GetDriver(v);
+ if (driverName && *driverName) {
+ GWEN_MSG_ENDPOINT *ep;
+
+ ep=AqHomeData_GetIpcEndpointByServiceName(aqh, driverName);
+ if (ep) {
+ GWEN_MSG *driverMsg;
+
+ DBG_INFO(AQH_LOGDOMAIN, "Sending SETDATA msg to driver endpoint (%s)", GWEN_MsgEndpoint_GetName(ep));
+ driverMsg=AQH_SingleDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA,
+ AQH_Value_GetNameForDriver(v),
+ AQH_Value_GetValueUnits(v),
+ AQH_Value_GetValueType(v),
+ timestamp,
+ datapoint);
+ GWEN_MsgEndpoint_AddSendMessage(ep, driverMsg);
+ return AQH_MSG_IPC_SUCCESS;
+ }
+ else {
+ DBG_INFO(NULL, "Driver \"%s\" not available", driverName);
+ return AQH_MSG_IPC_ERROR_GENERIC;
+ }
+ }
+ else {
+ DBG_INFO(NULL, "No driver name");
+ return AQH_MSG_IPC_ERROR_GENERIC;
+ }
}
diff --git a/apps/aqhome-data/c_updatedata.c b/apps/aqhome-data/c_updatedata.c
index eb526d2..d681829 100644
--- a/apps/aqhome-data/c_updatedata.c
+++ b/apps/aqhome-data/c_updatedata.c
@@ -13,6 +13,7 @@
#include "./c_updatedata.h"
#include "./aqhome_data_p.h"
+#include "./loop.h"
#include "aqhome/ipc/data/ipc_data.h"
#include "aqhome/ipc/data/msg_data_datapoints.h"
#include "aqhome/ipc/endpoint_ipc.h"
@@ -38,7 +39,6 @@
static int _readDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, uint32_t numValues);
static void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const AQH_VALUE *v,
const uint64_t *dataPoints, uint32_t numValues);
-static AQH_VALUE *_getOrCreateValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const char *nameForDriver, const char *units);
@@ -64,7 +64,7 @@ void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const
if (s && *s) {
AQH_VALUE *v;
- v=_getOrCreateValue(aqh, ep, s, AQH_DataPointsDataIpcMsg_GetUnits(recvdMsg));
+ v=AqHomeData_GetOrCreateValueForDriver(aqh, ep, s, AQH_DataPointsDataIpcMsg_GetUnits(recvdMsg), 0);
if (v==NULL) {
resultCode=AQH_MSG_IPC_ERROR_PERMS;
}
@@ -107,7 +107,6 @@ void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const
}
-
int _readDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, uint32_t numValues)
{
uint32_t i;
@@ -167,44 +166,3 @@ void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc,
-AQH_VALUE *_getOrCreateValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const char *nameForDriver, const char *units)
-{
- const char *serviceName;
- AQH_VALUE *v;
- GWEN_BUFFER *buf;
-
- serviceName=AQH_IpcEndpoint_GetServiceName(ep);
-
- buf=GWEN_Buffer_new(0, 256, 0, 1);
- if (serviceName && *serviceName) {
- GWEN_Buffer_AppendString(buf, serviceName);
- GWEN_Buffer_AppendString(buf, "/");
- }
- else {
- GWEN_Buffer_AppendString(buf, "unknown/");
- }
- GWEN_Buffer_AppendString(buf, nameForDriver);
-
- v=AQH_Storage_GetValueByNameForSystem(aqh->storage, GWEN_Buffer_GetStart(buf));
- if (v==NULL) {
- if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_ADDVALUE) {
- DBG_INFO(AQH_LOGDOMAIN, "Creating value \"%s\"", GWEN_Buffer_GetStart(buf));
- v=AQH_Value_new();
- AQH_Value_SetDriver(v, serviceName);
- AQH_Value_SetNameForDriver(v, nameForDriver);
- AQH_Value_SetNameForSystem(v, GWEN_Buffer_GetStart(buf));
- AQH_Value_SetValueUnits(v, units);
- AQH_Storage_AddValue(aqh->storage, v);
- }
- else {
- DBG_ERROR(AQH_LOGDOMAIN, "No permissions to create value \"%s\"", GWEN_Buffer_GetStart(buf));
- GWEN_Buffer_free(buf);
- return NULL;
- }
- }
- GWEN_Buffer_free(buf);
- return v;
-}
-
-
-
diff --git a/apps/aqhome-data/loop.c b/apps/aqhome-data/loop.c
index 48ae524..44a5fa4 100644
--- a/apps/aqhome-data/loop.c
+++ b/apps/aqhome-data/loop.c
@@ -18,10 +18,12 @@
#include "./c_getlastdatapoint.h"
#include "./c_getvalues.h"
#include "./c_setdata.h"
+#include "./c_addvalue.h"
#include "./aqhome_data_p.h"
#include "aqhome/ipc/data/ipc_data.h"
#include "aqhome/ipc/data/msg_data_values.h"
#include "aqhome/ipc/data/msg_data_datapoints.h"
+#include "aqhome/ipc/endpoint_ipc.h"
#include "aqhome/ipc/msg_ipc_result.h"
#include
@@ -95,6 +97,52 @@ int AqHomeData_WriteStorageIfChanged(AQHOME_DATA *aqh)
+AQH_VALUE *AqHomeData_GetOrCreateValueForDriver(AQHOME_DATA *aqh,
+ GWEN_MSG_ENDPOINT *epDriver,
+ const char *nameForDriver,
+ const char *units,
+ int valueType)
+{
+ const char *serviceName;
+ AQH_VALUE *v;
+ GWEN_BUFFER *buf;
+
+ serviceName=AQH_IpcEndpoint_GetServiceName(epDriver);
+
+ buf=GWEN_Buffer_new(0, 256, 0, 1);
+ if (serviceName && *serviceName) {
+ GWEN_Buffer_AppendString(buf, serviceName);
+ GWEN_Buffer_AppendString(buf, "/");
+ }
+ else {
+ GWEN_Buffer_AppendString(buf, "unknown/");
+ }
+ GWEN_Buffer_AppendString(buf, nameForDriver);
+
+ v=AQH_Storage_GetValueByNameForSystem(aqh->storage, GWEN_Buffer_GetStart(buf));
+ if (v==NULL) {
+ if (AQH_IpcEndpoint_GetPermissions(epDriver) & AQH_IPCENDPOINT_PERMS_ADDVALUE) {
+ DBG_INFO(AQH_LOGDOMAIN, "Creating value \"%s\"", GWEN_Buffer_GetStart(buf));
+ v=AQH_Value_new();
+ AQH_Value_SetDriver(v, serviceName);
+ AQH_Value_SetNameForDriver(v, nameForDriver);
+ AQH_Value_SetNameForSystem(v, GWEN_Buffer_GetStart(buf));
+ AQH_Value_SetValueUnits(v, units);
+ AQH_Value_SetValueType(v, valueType);
+ AQH_Storage_AddValue(aqh->storage, v);
+ }
+ else {
+ DBG_ERROR(AQH_LOGDOMAIN, "No permissions to create value \"%s\"", GWEN_Buffer_GetStart(buf));
+ GWEN_Buffer_free(buf);
+ return NULL;
+ }
+ }
+ GWEN_Buffer_free(buf);
+ return v;
+}
+
+
+
void _readAndHandleIpcMessages(AQHOME_DATA *aqh)
{
if (aqh->ipcdEndpoint) {
@@ -136,6 +184,7 @@ void _handleIpcMsg(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg)
case AQH_MSGTYPE_IPC_DATA_GETDATA_REQ: AqHomeData_HandleGetDataPoints(aqh, ep, msg); break;
case AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ: AqHomeData_HandleGetLastDataPoint(aqh, ep, msg); break;
case AQH_MSGTYPE_IPC_DATA_SETDATA: AqHomeData_HandleSetData(aqh, ep, msg); break;
+ case AQH_MSGTYPE_IPC_DATA_ADDVALUE: AqHomeData_HandleAddValue(aqh, ep, msg); break;
default: break;
}
}
diff --git a/apps/aqhome-data/loop.h b/apps/aqhome-data/loop.h
index 0da8397..a60a1b3 100644
--- a/apps/aqhome-data/loop.h
+++ b/apps/aqhome-data/loop.h
@@ -17,6 +17,12 @@ void AqHomeData_Loop(AQHOME_DATA *aqh, int timeoutInMsecs);
int AqHomeData_WriteStorageIfChanged(AQHOME_DATA *aqh);
+AQH_VALUE *AqHomeData_GetOrCreateValueForDriver(AQHOME_DATA *aqh,
+ GWEN_MSG_ENDPOINT *epDriver,
+ const char *nameForDriver,
+ const char *units,
+ int valueType);
+
#endif
diff --git a/apps/aqhome-tool/data/getdatapoints.c b/apps/aqhome-tool/data/getdatapoints.c
index 458d8ed..9f9538d 100644
--- a/apps/aqhome-tool/data/getdatapoints.c
+++ b/apps/aqhome-tool/data/getdatapoints.c
@@ -16,6 +16,7 @@
#include "aqhome/msg/msg_node.h"
#include "aqhome/ipc/msg_ipc_result.h"
#include "aqhome/ipc/data/msg_data_datapoints.h"
+#include "aqhome/ipc/data/msg_data_getdata.h"
#include "aqhome/ipc/data/ipc_data.h"
#include
@@ -263,12 +264,8 @@ int _doGetDataPoints(GWEN_DB_NODE *dbArgs)
void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, uint64_t tsBegin, uint64_t tsEnd)
{
GWEN_MSG *msgOut;
- uint64_t array[2];
- array[0]=tsBegin;
- array[1]=tsEnd;
-
- msgOut=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, 0, 0, valueName, NULL, array, 2);
+ msgOut=AQH_GetDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, valueName, tsBegin, tsEnd);
GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut);
}
diff --git a/apps/aqhome-tool/data/setdata.c b/apps/aqhome-tool/data/setdata.c
index 5dc2d0d..6d404c1 100644
--- a/apps/aqhome-tool/data/setdata.c
+++ b/apps/aqhome-tool/data/setdata.c
@@ -15,7 +15,7 @@
#include "aqhome/msg/msg_node.h"
#include "aqhome/ipc/msg_ipc_result.h"
-#include "aqhome/ipc/data/msg_data_datapoints.h"
+#include "aqhome/ipc/data/msg_data_singledata.h"
#include "aqhome/ipc/data/ipc_data.h"
#include
@@ -262,14 +262,8 @@ int _doSetData(GWEN_DB_NODE *dbArgs)
void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, double dataToSend)
{
GWEN_MSG *msgOut;
- union {double f; uint64_t i;} u;
- uint64_t arrayToSend[2];
- u.f=dataToSend;
- arrayToSend[0]=0;
- arrayToSend[1]=u.i;
-
- msgOut=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, 0, 0, valueName, valueUnits, arrayToSend, 1);
+ msgOut=AQH_SingleDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, valueName, valueUnits, 0, 0, dataToSend);
GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut);
}
diff --git a/aqhome/data/value.t2d b/aqhome/data/value.t2d
index 26ab7a7..77b233e 100644
--- a/aqhome/data/value.t2d
+++ b/aqhome/data/value.t2d
@@ -31,8 +31,11 @@
- -
- numeric type
+
-
+ sensor
+
+ -
+ actor
diff --git a/aqhome/ipc/data/0BUILD b/aqhome/ipc/data/0BUILD
index 456f52e..10f885a 100644
--- a/aqhome/ipc/data/0BUILD
+++ b/aqhome/ipc/data/0BUILD
@@ -49,6 +49,10 @@
msg_data_values.h
msg_data_datapoints.h
msg_data_connect.h
+ msg_data_addvalue.h
+ msg_data_singledata.h
+ msg_data_multidata.h
+ msg_data_getdata.h
@@ -63,6 +67,10 @@
msg_data_values.c
msg_data_datapoints.c
msg_data_connect.c
+ msg_data_addvalue.c
+ msg_data_singledata.c
+ msg_data_multidata.c
+ msg_data_getdata.c
diff --git a/aqhome/ipc/data/ipc_data.h b/aqhome/ipc/data/ipc_data.h
index 83d8ee8..0f2fd45 100644
--- a/aqhome/ipc/data/ipc_data.h
+++ b/aqhome/ipc/data/ipc_data.h
@@ -23,19 +23,21 @@
#define AQH_MSGTYPE_IPC_DATA_CONNECT_REQ 0x010 /* serviceName, userName, password */
-#define AQH_MSGTYPE_IPC_DATA_UPDATEDATA 0x100 /* AQH_DataPointsDataIpcMsg */
-#define AQH_MSGTYPE_IPC_DATA_DATACHANGED 0x200 /* AQH_DataPointsDataIpcMsg */
+#define AQH_MSGTYPE_IPC_DATA_UPDATEDATA 0x100 /* AQH_DataPointsDataIpcMsg */ /* TODO Multi */
+#define AQH_MSGTYPE_IPC_DATA_DATACHANGED 0x200 /* AQH_DataPointsDataIpcMsg */ /* TODO */
-#define AQH_MSGTYPE_IPC_DATA_SETDATA 0x300 /* AQH_DataPointsDataIpcMsg */
+#define AQH_MSGTYPE_IPC_DATA_SETDATA 0x300 /* AQH_SingleDataDataIpcMsg */ /* Single */
-#define AQH_MSGTYPE_IPC_DATA_GETDATA_REQ 0x500 /* AQH_DataPointsDataIpcMsg (1 pair: fromTime, toTime) */
-#define AQH_MSGTYPE_IPC_DATA_GETDATA_RSP 0x600 /* AQH_DataPointsDataIpcMsg */
+#define AQH_MSGTYPE_IPC_DATA_ADDVALUE 0x400 /* AQH_AddValueDataIpcMsg */
+
+#define AQH_MSGTYPE_IPC_DATA_GETDATA_REQ 0x500 /* AQH_GetDataDataIpcMsg */
+#define AQH_MSGTYPE_IPC_DATA_GETDATA_RSP 0x600 /* AQH_DataPointsDataIpcMsg */ /* TODO */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ 0x700 /* AQH_DataPointsDataIpcMsg (0 datapoints) */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_RSP 0x800 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ 0x900 /* GWEN_IpcMsg */
-#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0xa00 /* AQH_ValuesDataIpcMsg */
+#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0xa00 /* AQH_ValuesDataIpcMsg */ /* TODO */
diff --git a/aqhome/ipc/data/msg_data_addvalue.c b/aqhome/ipc/data/msg_data_addvalue.c
new file mode 100644
index 0000000..c3d0fa1
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_addvalue.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * 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.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+
+
+#define AQH_MSGDATA_ADDVALUE_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD
+
+
+
+
+GWEN_MSG *AQH_AddValueDataIpcMsg_new(uint16_t code,
+ const char *valueName,
+ const char *valueUnits,
+ int valueType)
+{
+ GWEN_MSG *msg;
+ GWEN_BUFFER *buf;
+
+ buf=GWEN_Buffer_new(0, 256, 0, 1);
+ if (valueName && *valueName)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_ADDVALUE_TAGS_NAME, valueName, buf);
+ if (valueUnits && *valueUnits)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_ADDVALUE_TAGS_UNITS, valueUnits, buf);
+ GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_ADDVALUE_TAGS_TYPE, valueType, buf);
+
+ msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code,
+ GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
+ GWEN_Buffer_free(buf);
+ return msg;
+}
+
+
+
+
+void AQH_AddValueDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
+{
+ if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_ADDVALUE_MINSIZE) {
+ GWEN_TAG16_LIST *tagList;
+ char *valueName=NULL;
+ char *valueUnits=NULL;
+ int valueType;
+
+ tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_UNITS);
+ valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_ADDVALUE_TAGS_TYPE);
+ valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0;
+ }
+
+ GWEN_Buffer_AppendArgs(dbuf,
+ "ADDVALUE (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d)\n",
+ GWEN_IpcMsg_GetCode(msg),
+ GWEN_IpcMsg_GetProtoId(msg),
+ GWEN_IpcMsg_GetProtoVersion(msg),
+ valueName?valueName:"",
+ valueUnits?valueUnits:"",
+ valueType);
+ free(valueUnits);
+ free(valueName);
+ GWEN_Tag16_List_free(tagList);
+ }
+}
+
+
+
+
+
+
+
diff --git a/aqhome/ipc/data/msg_data_addvalue.h b/aqhome/ipc/data/msg_data_addvalue.h
new file mode 100644
index 0000000..9adb02c
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_addvalue.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * 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 AQH_MSG_IPC_DATA_ADDVALUE_H
+#define AQH_MSG_IPC_DATA_ADDVALUE_H
+
+
+#include
+
+#include
+
+#include
+
+
+/**
+ * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUE_REQ.
+ */
+
+#define AQH_MSGDATA_ADDVALUE_TAGS_NAME 0x0001
+#define AQH_MSGDATA_ADDVALUE_TAGS_UNITS 0x0002
+#define AQH_MSGDATA_ADDVALUE_TAGS_TYPE 0x0003
+
+
+
+AQHOME_API GWEN_MSG *AQH_AddValueDataIpcMsg_new(uint16_t code,
+ const char *valueName,
+ const char *valueUnits,
+ int valueType);
+
+AQHOME_API void AQH_AddValueDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
+
+
+
+
+
+
+
+#endif
+
+
+
diff --git a/aqhome/ipc/data/msg_data_getdata.c b/aqhome/ipc/data/msg_data_getdata.c
new file mode 100644
index 0000000..bf7e878
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_getdata.c
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * 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.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+
+
+#define AQH_MSGDATA_GETDATA_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD
+
+
+
+
+GWEN_MSG *AQH_GetDataDataIpcMsg_new(uint16_t code, const char *valueName, uint64_t tsBegin, uint64_t tsEnd)
+{
+ GWEN_MSG *msg;
+ GWEN_BUFFER *buf;
+
+ buf=GWEN_Buffer_new(0, 256, 0, 1);
+ if (valueName && *valueName)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_GETDATA_TAGS_NAME, valueName, buf);
+ GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_BEGIN, tsBegin, buf);
+ GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_END, tsEnd, buf);
+
+ msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code,
+ GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
+ GWEN_Buffer_free(buf);
+ return msg;
+}
+
+
+
+
+void AQH_GetDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
+{
+ if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_GETDATA_MINSIZE) {
+ GWEN_TAG16_LIST *tagList;
+ char *valueName=NULL;
+ uint64_t tsBegin=0;
+ uint64_t tsEnd=0;
+
+ tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN);
+ tsBegin=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_GETDATA_TAGS_END);
+ tsEnd=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+ }
+
+ GWEN_Buffer_AppendArgs(dbuf,
+ "GETDATA (code=%d, proto=%d, proto version=%d, name=%s, tsBegin=%lu, tsEnd=%lu)\n",
+ GWEN_IpcMsg_GetCode(msg),
+ GWEN_IpcMsg_GetProtoId(msg),
+ GWEN_IpcMsg_GetProtoVersion(msg),
+ valueName?valueName:"",
+ (unsigned long int) tsBegin,
+ (unsigned long int) tsEnd);
+ free(valueName);
+ GWEN_Tag16_List_free(tagList);
+ }
+}
+
+
+
+
+
+
+
diff --git a/aqhome/ipc/data/msg_data_getdata.h b/aqhome/ipc/data/msg_data_getdata.h
new file mode 100644
index 0000000..88b98fb
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_getdata.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * 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 AQH_MSG_IPC_DATA_GETDATA_H
+#define AQH_MSG_IPC_DATA_GETDATA_H
+
+
+#include
+
+#include
+
+#include
+
+
+/**
+ * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUE_REQ.
+ */
+
+#define AQH_MSGDATA_GETDATA_TAGS_NAME 0x0001
+#define AQH_MSGDATA_GETDATA_TAGS_BEGIN 0x0020
+#define AQH_MSGDATA_GETDATA_TAGS_END 0x0021
+
+
+
+AQHOME_API GWEN_MSG *AQH_GetDataDataIpcMsg_new(uint16_t code, const char *valueName, uint64_t tsBegin, uint64_t tsEnd);
+
+AQHOME_API void AQH_GetDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
+
+
+
+
+
+
+
+#endif
+
+
+
diff --git a/aqhome/ipc/data/msg_data_multidata.c b/aqhome/ipc/data/msg_data_multidata.c
new file mode 100644
index 0000000..c28cb8e
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_multidata.c
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * 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.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+
+
+#define AQH_MSGDATA_MULTIDATA_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD
+
+
+
+
+GWEN_MSG *AQH_MultiDataDataIpcMsg_new(uint16_t code,
+ const char *valueName, const char *valueUnits, int valueType,
+ const uint64_t *i64Ptr, int numOfDataPoints)
+{
+ GWEN_MSG *msg;
+ GWEN_BUFFER *buf;
+
+ buf=GWEN_Buffer_new(0, 256, 0, 1);
+ if (valueName && *valueName)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_MULTIDATA_TAGS_NAME, valueName, buf);
+ if (valueUnits && *valueUnits)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_MULTIDATA_TAGS_UNITS, valueUnits, buf);
+ GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_MULTIDATA_TAGS_TYPE, valueType, buf);
+ if (i64Ptr && numOfDataPoints)
+ GWEN_Tag16_WriteTagToBuffer(AQH_MSGDATA_MULTIDATA_TAGS_DATA, (const uint8_t*)i64Ptr, numOfDataPoints*2*sizeof(uint64_t), buf);
+
+ msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code,
+ GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
+ GWEN_Buffer_free(buf);
+ return msg;
+}
+
+
+
+
+void AQH_MultiDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
+{
+ if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_MULTIDATA_MINSIZE) {
+ GWEN_TAG16_LIST *tagList;
+ char *valueName=NULL;
+ char *valueUnits=NULL;
+ int valueType;
+ unsigned int numberOfPoints=0;
+
+ tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_MULTIDATA_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_MULTIDATA_TAGS_UNITS);
+ valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_MULTIDATA_TAGS_TYPE);
+ valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_MULTIDATA_TAGS_DATA);
+ numberOfPoints=(tag?GWEN_Tag16_GetTagLength(tag):0)/(2*sizeof(uint64_t));
+ }
+
+ GWEN_Buffer_AppendArgs(dbuf,
+ "MULTIDATA (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, datapoints=%u)\n",
+ GWEN_IpcMsg_GetCode(msg),
+ GWEN_IpcMsg_GetProtoId(msg),
+ GWEN_IpcMsg_GetProtoVersion(msg),
+ valueName?valueName:"",
+ valueUnits?valueUnits:"",
+ valueType,
+ numberOfPoints);
+ free(valueUnits);
+ free(valueName);
+ GWEN_Tag16_List_free(tagList);
+ }
+}
+
+
+
+
+
+
+
diff --git a/aqhome/ipc/data/msg_data_multidata.h b/aqhome/ipc/data/msg_data_multidata.h
new file mode 100644
index 0000000..a404771
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_multidata.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * 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 AQH_MSG_IPC_DATA_MULTIDATA_H
+#define AQH_MSG_IPC_DATA_MULTIDATA_H
+
+
+#include
+
+#include
+
+#include
+
+
+#define AQH_MSGDATA_MULTIDATA_TAGS_NAME 0x0001
+#define AQH_MSGDATA_MULTIDATA_TAGS_UNITS 0x0002
+#define AQH_MSGDATA_MULTIDATA_TAGS_TYPE 0x0003
+#define AQH_MSGDATA_MULTIDATA_TAGS_DATA 0x0010
+
+
+
+AQHOME_API GWEN_MSG *AQH_MultiDataDataIpcMsg_new(uint16_t code,
+ const char *valueName, const char *valueUnits, int valueType,
+ const uint64_t *i64Ptr, int numOfDataPoints);
+
+AQHOME_API void AQH_MultiDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
+
+
+
+
+
+
+
+#endif
+
+
+
diff --git a/aqhome/ipc/data/msg_data_singledata.c b/aqhome/ipc/data/msg_data_singledata.c
new file mode 100644
index 0000000..9ae4e8c
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_singledata.c
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * 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.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+
+
+#define AQH_MSGDATA_SINGLEDATA_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD
+
+
+
+
+GWEN_MSG *AQH_SingleDataDataIpcMsg_new(uint16_t code,
+ const char *valueName,
+ const char *valueUnits,
+ int valueType,
+ uint64_t timestamp,
+ double datapoint)
+{
+ GWEN_MSG *msg;
+ GWEN_BUFFER *buf;
+ union {double f; uint64_t i;} u;
+
+ u.f=datapoint;
+ buf=GWEN_Buffer_new(0, 256, 0, 1);
+ if (valueName && *valueName)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_NAME, valueName, buf);
+ if (valueUnits && *valueUnits)
+ GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_UNITS, valueUnits, buf);
+ GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_TYPE, valueType, buf);
+ GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_TIME, timestamp, buf);
+ GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_DATA, u.i, buf);
+
+ msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code,
+ GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
+ GWEN_Buffer_free(buf);
+ return msg;
+}
+
+
+
+
+void AQH_SingleDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
+{
+ if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_SINGLEDATA_MINSIZE) {
+ GWEN_TAG16_LIST *tagList;
+ char *valueName=NULL;
+ char *valueUnits=NULL;
+ int valueType;
+ uint64_t timestamp;
+ union {double f; uint64_t i;} u;
+
+ tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
+ if (tagList) {
+ const GWEN_TAG16 *tag;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_NAME);
+ valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_UNITS);
+ valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_TYPE);
+ valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_TIME);
+ timestamp=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+
+ tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_DATA);
+ u.i=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0;
+ }
+
+ GWEN_Buffer_AppendArgs(dbuf,
+ "SINGLEDATA (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, time=%lu, data=%f)\n",
+ GWEN_IpcMsg_GetCode(msg),
+ GWEN_IpcMsg_GetProtoId(msg),
+ GWEN_IpcMsg_GetProtoVersion(msg),
+ valueName?valueName:"",
+ valueUnits?valueUnits:"",
+ valueType,
+ (unsigned long int) timestamp,
+ u.f);
+ free(valueUnits);
+ free(valueName);
+ GWEN_Tag16_List_free(tagList);
+ }
+}
+
+
+
+
+
+
+
diff --git a/aqhome/ipc/data/msg_data_singledata.h b/aqhome/ipc/data/msg_data_singledata.h
new file mode 100644
index 0000000..23d5b45
--- /dev/null
+++ b/aqhome/ipc/data/msg_data_singledata.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * 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 AQH_MSG_IPC_DATA_SINGLEDATA_H
+#define AQH_MSG_IPC_DATA_SINGLEDATA_H
+
+
+#include
+
+#include
+
+#include
+
+
+/**
+ * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUE_REQ.
+ */
+
+#define AQH_MSGDATA_SINGLEDATA_TAGS_NAME 0x0001
+#define AQH_MSGDATA_SINGLEDATA_TAGS_UNITS 0x0002
+#define AQH_MSGDATA_SINGLEDATA_TAGS_TYPE 0x0003
+#define AQH_MSGDATA_SINGLEDATA_TAGS_TIME 0x0010
+#define AQH_MSGDATA_SINGLEDATA_TAGS_DATA 0x0011
+
+
+
+AQHOME_API GWEN_MSG *AQH_SingleDataDataIpcMsg_new(uint16_t code,
+ const char *valueName,
+ const char *valueUnits,
+ int valueType,
+ uint64_t timestamp,
+ double datapoint);
+
+AQHOME_API void AQH_SingleDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
+
+
+
+
+
+
+
+#endif
+
+
+