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 + + +