Files
aqhomecontrol/apps/aqhome-data/c_updatedata.c
Martin Preuss 17d4ce5125 Change AQH_Value field NameForDriver to Name and make it only contain the value name.
Previously this field contained the device name, too. This would make it
necessary for drivers to remove the device part of the name when SetValue
is called. Instead the device name is now always provided by the driver in
the appropriate field DeviceNameForDriver.
2023-10-03 13:31:05 +02:00

149 lines
4.5 KiB
C

/****************************************************************************
* 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 <config.h>
#endif
#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_multidata.h"
#include "aqhome/ipc/endpoint_ipc.h"
#include "aqhome/ipc/msg_ipc_result.h"
#include "aqhome/ipc/msg_ipc_tag16.h"
#include <gwenhywfar/debug.h>
/* ------------------------------------------------------------------------------------------------
* defines
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static int _storeDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, int numValues);
static void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const AQH_VALUE *v,
const uint64_t *dataPoints, uint32_t numValues);
/* ------------------------------------------------------------------------------------------------
* implementations
* ------------------------------------------------------------------------------------------------
*/
void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
{
GWEN_MSG *outMsg;
int resultCode=AQH_MSG_IPC_SUCCESS;
const GWEN_TAG16 *tag;
AQH_VALUE *recvdValue;
const char *valueName;
const uint64_t *dataPoints=NULL;
unsigned int numberOfPoints=0;
AQH_MultiDataDataIpcMsg_Parse(recvdMsg, 0);
recvdValue=AQH_MultiDataDataIpcMsg_ReadValue(recvdMsg);
valueName=recvdValue?AQH_Value_GetName(recvdValue):NULL;
tag=AQH_Tag16IpcMsg_FindFirstTagByType(recvdMsg, AQH_MSGDATA_MULTIDATA_TAGS_DATA);
dataPoints=tag?((const uint64_t*)GWEN_Tag16_GetTagData(tag)):NULL;
numberOfPoints=(tag?GWEN_Tag16_GetTagLength(tag):0)/(2*sizeof(uint64_t));
if (numberOfPoints>0) {
AQH_VALUE *value;
value=AqHomeData_GetOrCreateValueForDriverWithTemplate(aqh, ep, recvdValue);
if (value) {
resultCode=_storeDataPoints(aqh, value, dataPoints, numberOfPoints);
if (resultCode==AQH_MSG_IPC_SUCCESS)
_sendDataChangedMsgToAllClients(aqh, ep, value, dataPoints, numberOfPoints);
}
else {
DBG_INFO(NULL, "No permissions to add datapoint for value \"%s\"", valueName);
resultCode=AQH_MSG_IPC_ERROR_PERMS;
}
}
else {
DBG_INFO(NULL, "No datapoints");
resultCode=AQH_MSG_IPC_ERROR_INVALID;
}
AQH_Value_free(recvdValue);
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode);
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
}
int _storeDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, int numValues)
{
uint32_t i;
for(i=0; i<numValues; i++) {
uint64_t timestamp;
union {double f; uint64_t i;} u;
int rv;
timestamp=*(dataPoints++);
u.i=*(dataPoints++);
rv=AQH_Storage_AddDatapoint(aqh->storage, AQH_Value_GetId(v), timestamp, u.f);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return AQH_MSG_IPC_ERROR_GENERIC;
}
else {
DBG_INFO(NULL, "Datapoint added for value \"%s\"", AQH_Value_GetNameForSystem(v));
}
} /* for */
return AQH_MSG_IPC_SUCCESS;
}
void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const AQH_VALUE *v,
const uint64_t *dataPoints, uint32_t numValues)
{
GWEN_MSG_ENDPOINT *ep;
ep=GWEN_MsgEndpoint_Tree2_GetFirstChild(aqh->ipcdEndpoint);
while(ep) {
if (ep!=epSrc) {
if (GWEN_MsgEndpoint_GetFlags(ep) & AQH_IPCENDPOINT_FLAGS_WANTUPDATES) {
GWEN_MSG *msg;
DBG_DEBUG(AQH_LOGDOMAIN, "Sending update msg to endpoint %s", GWEN_MsgEndpoint_GetName(ep));
msg=AQH_MultiDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_DATACHANGED, v, dataPoints, numValues);
GWEN_MsgEndpoint_AddSendMessage(ep, msg);
}
else {
DBG_DEBUG(AQH_LOGDOMAIN, "Endpoint %s doesn't want updates", GWEN_MsgEndpoint_GetName(ep));
}
}
else {
DBG_DEBUG(AQH_LOGDOMAIN, "Not sending update msg to source of updates");
}
ep=GWEN_MsgEndpoint_Tree2_GetNext(ep);
}
}