/**************************************************************************** * 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_setdata.h" #include "./server_p.h" #include "aqhome/data/value.h" #include "aqhome/msg/ipc/data/m_ipcd_setdata.h" #include "aqhome/msg/mqtt/m_mqtt_publish.h" #include "aqhome/ipc2/endpoint.h" #include #define DEBUG_DRY_RUN 1 /* don't actually set value if "1" */ /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, const char *valueName, const char *valueData); static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData); static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ void AQH_MqttLogServer_HandleSetData(AQH_OBJECT *o, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList) { if (o && msg) { AQH_MQTTLOG_SERVER *xo; xo=AQH_MqttLogServer_GetServerData(o); if (xo) { AQH_VALUE *recvdValue; DBG_ERROR(NULL, "Received SETDATA request"); recvdValue=AQH_IpcdMessageSetData_ReadValue(tagList); if (recvdValue) { const char *valueName; const char *deviceName; valueName=recvdValue?AQH_Value_GetName(recvdValue):NULL; deviceName=recvdValue?AQH_Value_GetDeviceName(recvdValue):NULL; if (valueName && deviceName) { AQHMQTT_DEVICE *device; device=AQH_MqttLogServer_FindRegisteredDevice(o, deviceName); if (device) { char *valueDataFreeable; DBG_ERROR(NULL, "Sending data to value \"%s\" of device \"%s\"", valueName, deviceName); valueDataFreeable=AQH_IpcdMessageSetData_ReadData(tagList); _sendDataForDevice(xo, device, valueName, valueDataFreeable); free(valueDataFreeable); } else { DBG_ERROR(NULL, "Device \"%s\" not found", deviceName); AQH_MqttLogServer_DumpRegisteredDevices(o); } } else { DBG_ERROR(NULL, "Either value name or device name missing in request"); } AQH_Value_free(recvdValue); } else { DBG_ERROR(NULL, "Request does not contain a value object"); } } } } void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, 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 */ DBG_ERROR(NULL, "Topic \"%s\" contains value \"%s\"", AQHMQTT_Topic_GetName(topic), valueName); _sendValueToMqtt(xo, deviceId, topic, valueData); } } /* if out */ topic=AQHMQTT_Topic_List_Next(topic); } /* while topic */ } } else { DBG_ERROR(NULL, "Device has no id"); } } void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData) { GWEN_BUFFER *buf; #if !DEBUG_DRY_RUN AQH_MESSAGE *msgOut; #endif buf=_createBufferForTopic(deviceId, topic); #if !DEBUG_DRY_RUN DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), (const uint8_t*) (valueData?valueData:NULL), valueData?strlen(valueData):0); if (msgOut) AQH_Endpoint_AddMsgOut(xo->mqttEndpoint, msgOut); else { DBG_ERROR(NULL, "Error creating message"); } #else DBG_ERROR(NULL, "Would MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); #endif 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_AppendString(buf, deviceId); s=AQHMQTT_Topic_GetAfterId(topic); if (s && *s) GWEN_Buffer_AppendString(buf, s); return buf; }