/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2024 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_setdata.h" #include "aqhome/data/value.h" #include "aqhome/ipc/data/msg_data_set.h" #include "aqhome/mqtt/msg_mqtt_publish.h" #include /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _sendDataForDevice(AQHOME_MQTT *aqh, const AQHMQTT_DEVICE *device, const char *valueName, const char *valueData); static void _sendValueToMqtt(AQHOME_MQTT *aqh, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData); static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ void AqHomeMqttLog_HandleSetData(AQHOME_MQTT *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg) { AQH_VALUE *recvdValue; DBG_ERROR(NULL, "Received SETDATA request"); recvdValue=AQH_SetDataIpcMsg_ReadValue(recvdMsg); if (recvdValue) { const char *valueName; const char *deviceName; valueName=recvdValue?AQH_Value_GetNameForSystem(recvdValue):NULL; deviceName=recvdValue?AQH_Value_GetDeviceName(recvdValue):NULL; if (deviceName) { AQHMQTT_DEVICE *device; device=AqHomeMqtt_FindRegisteredDevice(aqh, deviceName); if (device) { char *valueDataFreeable; valueDataFreeable=AQH_SetDataIpcMsg_ReadData(recvdMsg); _sendDataForDevice(aqh, device, valueName, valueDataFreeable); free(valueDataFreeable); } else { DBG_ERROR(NULL, "Device \"%s\" not found", deviceName); } } else { DBG_ERROR(NULL, "Request does not contain a device name"); } AQH_Value_free(recvdValue); } else { DBG_ERROR(NULL, "Request does not contain a value object"); } } void _sendDataForDevice(AQHOME_MQTT *aqh, const AQHMQTT_DEVICE *device, const char *valueName, const char *valueData) { const char *deviceId; deviceId=AQHMQTT_Device_GetId(device); if (deviceId && *deviceId) { AQHMQTT_TOPIC_LIST *topicList; topicList=AQHMQTT_Device_GetTopicList(device); if (topicList) { AQHMQTT_TOPIC *topic; topic=AQHMQTT_Topic_List_First(topicList); while(topic) { if (AQHMQTT_Topic_GetDirection(topic)==AQHMQTT_TopicDir_Out) { AQHMQTT_VALUE_LIST *valueList; AQHMQTT_VALUE *value; valueList=AQHMQTT_Topic_GetValueList(topic); value=valueList?AQHMQTT_Value_List_GetByName(valueList, valueName):NULL; if (value) { /* found value, create publish msg, send */ _sendValueToMqtt(aqh, deviceId, topic, valueData); } } /* if out */ topic=AQHMQTT_Topic_List_Next(topic); } /* while topic */ } } else { DBG_ERROR(NULL, "Device has no id"); } } void _sendValueToMqtt(AQHOME_MQTT *aqh, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData) { GWEN_MSG_ENDPOINT *ep; GWEN_BUFFER *buf; GWEN_MSG *msgOut; ep=AqHomeMqtt_GetMqttEndpoint(aqh); buf=_createBufferForTopic(deviceId, topic); DBG_INFO(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); msgOut=AQH_PublishMqttMsg_new(0, 0, GWEN_Buffer_GetStart(buf), (const uint8_t*) (valueData?valueData:NULL), valueData?strlen(valueData):0); if (msgOut) { GWEN_MsgEndpoint_AddSendMessage(ep, msgOut); } else { DBG_ERROR(NULL, "Error creating message"); } GWEN_Buffer_free(buf); } GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic) { GWEN_BUFFER *buf; const char *s; buf=GWEN_Buffer_new(0, 256, 0, 1); s=AQHMQTT_Topic_GetBeforeId(topic); if (s && *s) { GWEN_Buffer_AppendString(buf, s); GWEN_Buffer_AppendByte(buf, '/'); } GWEN_Buffer_AppendString(buf, deviceId); s=AQHMQTT_Topic_GetAfterId(topic); if (s && *s) { GWEN_Buffer_AppendByte(buf, '/'); GWEN_Buffer_AppendString(buf, s); } return buf; }