From cbf88e05fe8990b8329cdee58cd381d9e9ae15a7 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Wed, 25 Jun 2025 00:03:58 +0200 Subject: [PATCH] added "mode" argument to "getdata" command. --- apps/aqhome-data/s_getdatapoints.c | 104 +++++++++++++------------- apps/aqhome-tool/data/getdatapoints.c | 7 +- aqhome/msg/ipc/data/m_ipcd_getdata.c | 23 +++++- aqhome/msg/ipc/data/m_ipcd_getdata.h | 10 +++ 4 files changed, 87 insertions(+), 57 deletions(-) diff --git a/apps/aqhome-data/s_getdatapoints.c b/apps/aqhome-data/s_getdatapoints.c index f2db538..fd9993e 100644 --- a/apps/aqhome-data/s_getdatapoints.c +++ b/apps/aqhome-data/s_getdatapoints.c @@ -1,6 +1,6 @@ /**************************************************************************** * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * AqHome (c) by 2025 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. @@ -33,8 +33,8 @@ * ------------------------------------------------------------------------------------------------ */ -#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048 -#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024 +#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 1024 +#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 512 /* ------------------------------------------------------------------------------------------------ @@ -44,13 +44,15 @@ static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, + int mode, uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId); -static int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, +static int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, + uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId); -static int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId); +static int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId); +static int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId); static void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr, uint32_t refMsgId); -static void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint32_t refMsgId); @@ -79,16 +81,18 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A uint64_t tsBegin; uint64_t tsEnd; uint64_t numRequested; + int mode; tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0); tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0); numRequested=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_NUM, 0); + mode=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, AQH_MSGDATA_GETDATA_MODE_FIRST); value=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName); if (value) { int resultCode; - resultCode=_getAndSendDataPoints(xo->storage, ep, value, tsBegin, tsEnd, numRequested, refMsgId); + resultCode=_getAndSendDataPoints(xo->storage, ep, value, mode, tsBegin, tsEnd, numRequested, refMsgId); AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode); } else { @@ -114,30 +118,31 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, + int mode, uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId) { - if (num==0) - return _getAndSendDataPointsNoNum(storage, ep, value, tsBegin, tsEnd, refMsgId); - else if (num==1) { - _getAndSendLastDatapoint(storage, ep, value, refMsgId); - return AQH_MSGDATA_RESULT_SUCCESS; + switch(mode) { + case AQH_MSGDATA_GETDATA_MODE_FIRST: return _getAndSendDataPointsFirst(storage, ep, value, num, refMsgId); + case AQH_MSGDATA_GETDATA_MODE_PERIOD: return _getAndSendDataPointsPeriod(storage, ep, value, tsBegin, tsEnd, num, refMsgId); + default: + case AQH_MSGDATA_GETDATA_MODE_LAST: return _getAndSendDataPointsLast(storage, ep, value, num, refMsgId); } - else - return _getAndSendDataPointsWithNum(storage, ep, value, num, refMsgId); } -int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, - const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, - uint32_t refMsgId) +int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep, + const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num, + uint32_t refMsgId) { uint64_t valueId; uint64_t *tablePtr; valueId=AQH_Value_GetId(value); - tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES); + if (num==0 || num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES) + num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES; + tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, num); if (tablePtr) { _sendDataPointsResponse(ep, value, tablePtr, refMsgId); free(tablePtr); @@ -151,9 +156,9 @@ int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, -int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, - const AQH_VALUE *value, uint64_t num, - uint32_t refMsgId) +int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep, + const AQH_VALUE *value, uint64_t num, + uint32_t refMsgId) { uint64_t valueId; uint64_t *tablePtr; @@ -175,6 +180,30 @@ int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, +int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep, + const AQH_VALUE *value, uint64_t num, + uint32_t refMsgId) +{ + uint64_t valueId; + uint64_t *tablePtr; + + if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS) + num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS; + valueId=AQH_Value_GetId(value); + tablePtr=AQH_Storage_GetFirstNDataPoints(storage, valueId, num); + if (tablePtr) { + _sendDataPointsResponse(ep, value, tablePtr, refMsgId); + free(tablePtr); + return AQH_MSGDATA_RESULT_SUCCESS; + } + else { + DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value)); + return AQH_MSGDATA_RESULT_ERROR_NODATA; + } +} + + + void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr, uint32_t refMsgId) @@ -193,36 +222,3 @@ void _sendDataPointsResponse(AQH_OBJECT *ep, -void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep, - const AQH_VALUE *value, uint32_t refMsgId) -{ - int rv; - uint64_t timestamp=0; - double data=0.0; - - rv=AQH_Storage_GetLastDataPoint(storage, AQH_Value_GetId(value), ×tamp, &data); - if (rv<0) { - int resultCode; - - switch(rv) { - case GWEN_ERROR_INVALID: resultCode=AQH_MSGDATA_RESULT_ERROR_INVALID; break; - case GWEN_ERROR_NO_DATA: resultCode=AQH_MSGDATA_RESULT_ERROR_NODATA; break; - default: resultCode=AQH_MSGDATA_RESULT_ERROR_GENERIC; break; - } - AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode); - } - else { - AQH_MESSAGE *outMsg; - - outMsg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP, - AQH_Endpoint_GetNextMessageId(ep), refMsgId, - value, timestamp, data); - AQH_Endpoint_AddMsgOut(ep, outMsg); - } -} - - - - - - diff --git a/apps/aqhome-tool/data/getdatapoints.c b/apps/aqhome-tool/data/getdatapoints.c index cb4c57d..f4ebe4a 100644 --- a/apps/aqhome-tool/data/getdatapoints.c +++ b/apps/aqhome-tool/data/getdatapoints.c @@ -121,7 +121,12 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId) return NULL; } - return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, msgId, 0, valueName, tsBegin, tsEnd, num); + // TODO: use "mode" correctly + return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, + msgId, 0, + AQH_MSGDATA_GETDATA_MODE_LAST, + valueName, + tsBegin, tsEnd, num); } diff --git a/aqhome/msg/ipc/data/m_ipcd_getdata.c b/aqhome/msg/ipc/data/m_ipcd_getdata.c index 47b85cb..dcfd0bf 100644 --- a/aqhome/msg/ipc/data/m_ipcd_getdata.c +++ b/aqhome/msg/ipc/data/m_ipcd_getdata.c @@ -28,6 +28,8 @@ * ------------------------------------------------------------------------------------------------ */ +static const char *_modeToChar(int mode); + /* ------------------------------------------------------------------------------------------------ @@ -37,6 +39,7 @@ AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, + int mode, const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num) { AQH_MESSAGE *msg; @@ -49,6 +52,7 @@ AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code, GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_BEGIN, tsBegin, buf); GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_END, tsEnd, buf); GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_NUM, num, buf); + GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_MODE, mode, buf); msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId, GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf)); @@ -64,19 +68,22 @@ void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 char *valueName; uint64_t tsBegin; uint64_t tsEnd; + uint64_t mode; valueName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL):NULL; tsBegin=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0):0; tsEnd=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0):0; + mode=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, 0):0; GWEN_Buffer_AppendArgs(dbuf, - "GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, tsBegin=%lu, tsEnd=%lu)\n", + "GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, mode=%s, tsBegin=%lu, tsEnd=%lu)\n", AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)), sText?sText:"", AQH_IpcMessage_GetCode(msg), AQH_IpcMessage_GetProtoId(msg), AQH_IpcMessage_GetProtoVersion(msg), - valueName?valueName:"", + valueName?valueName:"", + _modeToChar(mode), (unsigned long int) tsBegin, (unsigned long int) tsEnd); free(valueName); @@ -85,3 +92,15 @@ void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 +const char *_modeToChar(int mode) +{ + switch(mode) { + case AQH_MSGDATA_GETDATA_MODE_FIRST: return "first"; + case AQH_MSGDATA_GETDATA_MODE_LAST: return "last"; + case AQH_MSGDATA_GETDATA_MODE_PERIOD: return "period"; + default: return "unknown"; + } +} + + + diff --git a/aqhome/msg/ipc/data/m_ipcd_getdata.h b/aqhome/msg/ipc/data/m_ipcd_getdata.h index 46ea85d..3993cb7 100644 --- a/aqhome/msg/ipc/data/m_ipcd_getdata.h +++ b/aqhome/msg/ipc/data/m_ipcd_getdata.h @@ -24,10 +24,20 @@ #define AQH_MSGDATA_GETDATA_TAGS_BEGIN 0x0020 #define AQH_MSGDATA_GETDATA_TAGS_END 0x0021 #define AQH_MSGDATA_GETDATA_TAGS_NUM 0x0022 +#define AQH_MSGDATA_GETDATA_TAGS_MODE 0x0023 + + +enum { + AQH_MSGDATA_GETDATA_MODE_FIRST=0, + AQH_MSGDATA_GETDATA_MODE_LAST, + AQH_MSGDATA_GETDATA_MODE_PERIOD +}; + AQHOME_API AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, + int mode, const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num); AQHOME_API void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList,