/**************************************************************************** * 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_updatedata.h" #include "./aqhome_data_p.h" #include "aqhome/ipc/data/ipc_data.h" #include "aqhome/ipc/data/msg_data_datapoints.h" #include "aqhome/ipc/endpoint_ipc.h" #include "aqhome/ipc/msg_ipc_result.h" #include /* ------------------------------------------------------------------------------------------------ * defines * ------------------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ 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); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *recvdMsg) { GWEN_MSG *outMsg; int resultCode=AQH_MSG_IPC_SUCCESS; if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_ADDDATA) { if (AQH_DataPointsDataIpcMsg_IsValid(recvdMsg)) { uint32_t numValues; numValues=AQH_DataPointsDataIpcMsg_GetNumValues(recvdMsg); if (numValues) { const char *s; s=AQH_DataPointsDataIpcMsg_GetValueName(recvdMsg); if (s && *s) { AQH_VALUE *v; v=_getOrCreateValue(aqh, ep, s, AQH_DataPointsDataIpcMsg_GetUnits(recvdMsg)); if (v==NULL) { resultCode=AQH_MSG_IPC_ERROR_PERMS; } else { const uint64_t *dataPoints; dataPoints=AQH_DataPointsDataIpcMsg_GetDataPoints(recvdMsg); if (dataPoints) resultCode=_readDataPoints(aqh, v, dataPoints, numValues); else { DBG_INFO(NULL, "No datapoints"); resultCode=AQH_MSG_IPC_ERROR_BADDATA; } if (resultCode==AQH_MSG_IPC_SUCCESS) _sendDataChangedMsgToAllClients(aqh, ep, v, dataPoints, numValues); } } else { DBG_INFO(NULL, "Value without name "); resultCode=AQH_MSG_IPC_ERROR_INVALID; } } else { DBG_INFO(NULL, "No datapoints"); resultCode=AQH_MSG_IPC_ERROR_BADDATA; } } else { DBG_INFO(NULL, "Invalid message received"); resultCode=AQH_MSG_IPC_ERROR_BADDATA; } } else { DBG_ERROR(AQH_LOGDOMAIN, "No permissions to add data"); resultCode=AQH_MSG_IPC_ERROR_PERMS; } outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode); GWEN_MsgEndpoint_AddSendMessage(ep, outMsg); } int _readDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, uint32_t numValues) { uint32_t i; for(i=0; istorage, 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_INFO(AQH_LOGDOMAIN, "Sending update msg to endpoint %s", GWEN_MsgEndpoint_GetName(ep)); msg=AQH_DataPointsDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_DATACHANGED, 0, /* flags */ AQH_Value_GetId(v), AQH_Value_GetNameForSystem(v), AQH_Value_GetValueUnits(v), dataPoints, numValues); GWEN_MsgEndpoint_AddSendMessage(ep, msg); } else { DBG_INFO(AQH_LOGDOMAIN, "Endpoint %s doesn't want updates", GWEN_MsgEndpoint_GetName(ep)); } } else { DBG_INFO(AQH_LOGDOMAIN, "Not sending update msg to source of updates"); } ep=GWEN_MsgEndpoint_Tree2_GetNext(ep); } } 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; }