/**************************************************************************** * This file is part of the project AqHome. * 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. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "./s_getvalues.h" #include "./server_p.h" #include "aqhome/aqhome.h" #include "aqhome/ipc2/endpoint.h" #include "aqhome/msg/ipc/m_ipc.h" #include "aqhome/msg/ipc/data/m_ipcd.h" #include "aqhome/msg/ipc/data/m_ipcd_getvalues.h" #include "aqhome/msg/ipc/data/m_ipcd_values.h" #include "aqhome/msg/ipc/m_ipc_result.h" #include "aqhome/msg/ipc/m_ipc_tag16.h" #include #include /* ------------------------------------------------------------------------------------------------ * defines * ------------------------------------------------------------------------------------------------ */ #define AQHOMEDATA_VALUESPERMSG 10 /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList); static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId); static void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId); static int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ void AqHomeDataServer_HandleGetValues(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList) { AQHOME_SERVER *xo; xo=AqHomeDataServer_GetServerData(o); if (xo) { AQH_VALUE_LIST *valueList; uint32_t refMsgId; refMsgId=AQH_IpcMessage_GetMsgId(msg); DBG_INFO(NULL, "HandleGetValues"); valueList=_getMatchingValueList(xo, tagList); if (valueList) { _sendValueList(ep, valueList, refMsgId); AQH_Value_List_free(valueList); } else { /* empty list */ _sendValueListMsg(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); } } } AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList) { const AQH_VALUE_LIST *origValueList; AQH_VALUE_LIST *tmpValueList=NULL; char *deviceName; int modality; deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME, NULL):NULL; modality=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETVALUES_TAGS_MODALITY, 0):0; origValueList=AQH_Storage_GetValueList(xo->storage); if (origValueList) { const AQH_VALUE *v; tmpValueList=AQH_Value_List_new(); v=AQH_Value_List_First(origValueList); while(v) { if (_valueMatches(v, deviceName, modality)) { AQH_VALUE *copyOfValue; copyOfValue=AQH_Value_dup(v); AQH_Value_List_Add(copyOfValue, tmpValueList); } v=AQH_Value_List_Next(v); } if (AQH_Value_List_GetCount(tmpValueList)<1) { AQH_Value_List_free(tmpValueList); tmpValueList=NULL; } } free(deviceName); return tmpValueList; } void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId) { AQH_VALUE_LIST *tmpValueList; const AQH_VALUE *v; tmpValueList=AQH_Value_List_new(); v=AQH_Value_List_First(vl); while(v) { const AQH_VALUE *next; AQH_VALUE *copyOfValue; next=AQH_Value_List_Next(v); copyOfValue=AQH_Value_dup(v); AQH_Value_List_Add(copyOfValue, tmpValueList); if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) { DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList)); _sendValueListMsg(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); AQH_Value_List_Clear(tmpValueList); } v=next; } if (AQH_Value_List_GetCount(tmpValueList)) { DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList)); _sendValueListMsg(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */ } AQH_Value_List_free(tmpValueList); } void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId) { AQH_MESSAGE *msg; DBG_INFO(NULL, "Sending msg (refMsgId=%d)", refMsgId); msg=AQH_IpcdMessageValues_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP, AQH_Endpoint_GetNextMessageId(ep), refMsgId, flags, vl); AQH_Endpoint_AddMsgOut(ep, msg); } int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality) { if (modality!=AQH_ValueModality_Unknown) { int valModality; valModality=AQH_Value_GetModality(v); if (valModality!=modality) return 0; } if (deviceName && *deviceName) { const char *s; s=AQH_Value_GetDeviceNameForSystem(v); if (s && *s && GWEN_Text_ComparePattern(s, deviceName, 0)==-1) return 0; } return 1; }