/**************************************************************************** * 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_getdevices.h" #include "./server_p.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_getdevices.h" #include "aqhome/msg/ipc/data/m_ipcd_devices.h" #include "aqhome/msg/ipc/m_ipc_result.h" #include "aqhome/msg/ipc/m_ipc_tag16.h" #include #include /* ------------------------------------------------------------------------------------------------ * defines * ------------------------------------------------------------------------------------------------ */ #define AQHOMEDATA_DEVICESPERMSG 10 /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static AQH_DEVICE_LIST *_getMatchingDeviceList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList); static int _deviceMatches(const AQH_DEVICE *dev, const char *deviceName); static void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t refMsgId); static void _sendDeviceListMsg(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ void AqHomeDataServer_HandleGetDevices(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_DEVICE_LIST *deviceList; uint32_t refMsgId; refMsgId=AQH_IpcMessage_GetMsgId(msg); DBG_INFO(NULL, "HandleGetDevices"); deviceList=_getMatchingDeviceList(xo, tagList); if (deviceList) { _sendDeviceList(ep, deviceList, refMsgId); AQH_Device_List_free(deviceList); } else { /* empty list */ _sendDeviceListMsg(ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); } } } AQH_DEVICE_LIST *_getMatchingDeviceList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList) { const AQH_DEVICE_LIST *origDeviceList; AQH_DEVICE_LIST *tmpDeviceList=NULL; char *deviceName; deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDEVICES_TAGS_DEVICENAME, NULL):NULL; origDeviceList=AQH_Storage_GetDeviceList(xo->storage); if (origDeviceList) { const AQH_DEVICE *dev; tmpDeviceList=AQH_Device_List_new(); dev=AQH_Device_List_First(origDeviceList); while(dev) { if (_deviceMatches(dev, deviceName)) { AQH_DEVICE *copyOfDevice; copyOfDevice=AQH_Device_dup(dev); AQH_Device_List_Add(copyOfDevice, tmpDeviceList); } dev=AQH_Device_List_Next(dev); } if (AQH_Device_List_GetCount(tmpDeviceList)<1) { AQH_Device_List_free(tmpDeviceList); tmpDeviceList=NULL; } } free(deviceName); return tmpDeviceList; } int _deviceMatches(const AQH_DEVICE *dev, const char *deviceName) { if (deviceName && *deviceName) { const char *s; s=AQH_Device_GetNameForSystem(dev); if (s && *s && GWEN_Text_ComparePattern(s, deviceName, 0)==-1) return 0; } return 1; } void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *deviceList, uint32_t refMsgId) { AQH_DEVICE_LIST *tmpDeviceList; const AQH_DEVICE *dev; DBG_INFO(NULL, "Sending entries in multiple messages"); tmpDeviceList=AQH_Device_List_new(); dev=AQH_Device_List_First(deviceList); while(dev) { const AQH_DEVICE *next; AQH_DEVICE *copyOfDevice; next=AQH_Device_List_Next(dev); copyOfDevice=AQH_Device_dup(dev); AQH_Device_List_Add(copyOfDevice, tmpDeviceList); if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) { DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList)); _sendDeviceListMsg(ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); AQH_Device_List_Clear(tmpDeviceList); } dev=next; } if (AQH_Device_List_GetCount(tmpDeviceList)) { DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList)); _sendDeviceListMsg(ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); /* send remaining */ } AQH_Device_List_free(tmpDeviceList); } void _sendDeviceListMsg(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId) { AQH_MESSAGE *msg; DBG_INFO(NULL, "Sending msg (refMsgId=%d)", refMsgId); msg=AQH_IpcdMessageDevices_new(AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP, AQH_Endpoint_GetNextMessageId(ep), refMsgId, flags, vl); AQH_Endpoint_AddMsgOut(ep, msg); }