234 lines
7.0 KiB
C
234 lines
7.0 KiB
C
/****************************************************************************
|
|
* 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 <config.h>
|
|
#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 <gwenhywfar/debug.h>
|
|
|
|
|
|
#define DEBUG_DRY_RUN 0 /* don't actually set value if "1" */
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device,
|
|
const char *valueName, double valueData);
|
|
static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo,
|
|
const AQHMQTT_DEVICE *device,
|
|
const AQHMQTT_TOPIC *topic,
|
|
const AQHMQTT_VALUE *value,
|
|
double valueData);
|
|
static const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double 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) {
|
|
double valueData;
|
|
|
|
DBG_ERROR(NULL, "Sending data to value \"%s\" of device \"%s\"", valueName, deviceName);
|
|
valueData=AQH_IpcdMessageSetData_ReadData(tagList);
|
|
_sendDataForDevice(xo, device, valueName, valueData);
|
|
}
|
|
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, double 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, device, topic, value, 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 AQHMQTT_DEVICE *device,
|
|
const AQHMQTT_TOPIC *topic,
|
|
const AQHMQTT_VALUE *value,
|
|
double valueData)
|
|
{
|
|
const char *deviceId;
|
|
const char *translatedValue;
|
|
GWEN_BUFFER *buf;
|
|
#if !DEBUG_DRY_RUN
|
|
AQH_MESSAGE *msgOut;
|
|
#endif
|
|
|
|
deviceId=AQHMQTT_Device_GetId(device);
|
|
buf=_createBufferForTopic(deviceId, topic);
|
|
translatedValue=_valueTranslatedForDriver(value, valueData);
|
|
if (translatedValue && *translatedValue) {
|
|
DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), translatedValue);
|
|
msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), (const uint8_t*)translatedValue, strlen(translatedValue));
|
|
}
|
|
else {
|
|
GWEN_BUFFER *vbuf;
|
|
|
|
vbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
|
GWEN_Buffer_AppendArgs(vbuf, "%f", valueData);
|
|
DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetStart(vbuf));
|
|
msgOut=AQH_MqttMessagePublish_new(0, 0,
|
|
GWEN_Buffer_GetStart(buf),
|
|
(const uint8_t*)GWEN_Buffer_GetStart(vbuf),
|
|
GWEN_Buffer_GetUsedBytes(vbuf));
|
|
GWEN_Buffer_free(vbuf);
|
|
}
|
|
|
|
#if !DEBUG_DRY_RUN
|
|
if (msgOut)
|
|
AQH_Endpoint_AddMsgOut(xo->mqttEndpoint, msgOut);
|
|
else {
|
|
DBG_ERROR(NULL, "Error creating message");
|
|
}
|
|
#endif
|
|
GWEN_Buffer_free(buf);
|
|
}
|
|
|
|
|
|
|
|
const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double valueData)
|
|
{
|
|
const AQHMQTT_TRANSLATION_LIST *translationList;
|
|
|
|
translationList=AQHMQTT_Value_GetTranslationList(value);
|
|
if (translationList) {
|
|
const AQHMQTT_TRANSLATION *t;
|
|
int valueAsInt;
|
|
|
|
valueAsInt=(int) valueData;
|
|
t=AQHMQTT_Translation_List_GetByAqhValue(translationList, valueAsInt);
|
|
if (t) {
|
|
const char *s;
|
|
|
|
s=AQHMQTT_Translation_GetDriverValue(t);
|
|
DBG_ERROR(NULL, "Translated value %d to %s", valueAsInt, s);
|
|
return s;
|
|
}
|
|
else {
|
|
DBG_ERROR(NULL, "No translation found for %d", valueAsInt);
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERROR(NULL, "No translation list");
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|