diff --git a/apps/aqhome-mqttlog/0BUILD b/apps/aqhome-mqttlog/0BUILD index a233471..9dc0c92 100644 --- a/apps/aqhome-mqttlog/0BUILD +++ b/apps/aqhome-mqttlog/0BUILD @@ -55,6 +55,7 @@ aqhome_mqtt.h aqhome_mqtt_p.h xmlread.h + c_setdata.h @@ -67,6 +68,7 @@ loop_mqtt.c main.c xmlread.c + c_setdata.c diff --git a/apps/aqhome-mqttlog/aqhome_mqtt.c b/apps/aqhome-mqttlog/aqhome_mqtt.c index c6b967f..dfbe1ea 100644 --- a/apps/aqhome-mqttlog/aqhome_mqtt.c +++ b/apps/aqhome-mqttlog/aqhome_mqtt.c @@ -112,6 +112,17 @@ void AqHomeMqtt_SetAvailableDeviceList(AQHOME_MQTT *aqh, AQHMQTT_DEVICE_LIST *dl +AQHMQTT_DEVICE *AqHomeMqtt_FindRegisteredDevice(AQHOME_MQTT *aqh, const char *wantedDeviceId) +{ + if (aqh && aqh->registeredDeviceList) + return AQHMQTT_Device_List_GetById(aqh->registeredDeviceList, wantedDeviceId); + + return NULL; +} + + + + diff --git a/apps/aqhome-mqttlog/aqhome_mqtt.h b/apps/aqhome-mqttlog/aqhome_mqtt.h index 1357be5..c8257c2 100644 --- a/apps/aqhome-mqttlog/aqhome_mqtt.h +++ b/apps/aqhome-mqttlog/aqhome_mqtt.h @@ -10,8 +10,8 @@ #define AQHOME_MQTT_H -#include "./mqttvalue.h" -#include "./mqtttopic.h" +//#include "./mqttvalue.h" +//#include "./mqtttopic.h" #include "aqhome-mqttlog/types/device.h" @@ -39,6 +39,7 @@ int AqHomeMqtt_GetTimeout(const AQHOME_MQTT *aqh); AQHMQTT_DEVICE_LIST *AqHomeMqtt_GetAvailableDeviceList(const AQHOME_MQTT *aqh); void AqHomeMqtt_SetAvailableDeviceList(AQHOME_MQTT *aqh, AQHMQTT_DEVICE_LIST *dl); +AQHMQTT_DEVICE *AqHomeMqtt_FindRegisteredDevice(AQHOME_MQTT *aqh, const char *wantedDeviceId); #endif diff --git a/apps/aqhome-mqttlog/aqhome_mqtt_p.h b/apps/aqhome-mqttlog/aqhome_mqtt_p.h index 7aa29d6..e9b364b 100644 --- a/apps/aqhome-mqttlog/aqhome_mqtt_p.h +++ b/apps/aqhome-mqttlog/aqhome_mqtt_p.h @@ -33,12 +33,8 @@ struct AQHOME_MQTT { char *pidFile; int timeout; /* timeout for run e.g. inside valgrind */ - AQH_MQTT_VALUE *mqttValueList; - AQH_MQTT_TOPIC *mqttTopicList; - AQHMQTT_DEVICE_LIST *availableDeviceList; AQHMQTT_DEVICE_LIST *registeredDeviceList; - }; diff --git a/apps/aqhome-mqttlog/c_setdata.c b/apps/aqhome-mqttlog/c_setdata.c new file mode 100644 index 0000000..50bb13c --- /dev/null +++ b/apps/aqhome-mqttlog/c_setdata.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * 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; +} + + + + + + diff --git a/apps/aqhome-mqttlog/c_setdata.h b/apps/aqhome-mqttlog/c_setdata.h new file mode 100644 index 0000000..437a190 --- /dev/null +++ b/apps/aqhome-mqttlog/c_setdata.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_MQTTLOG_C_SETDATA_H +#define AQHOME_MQTTLOG_C_SETDATA_H + + +#include "./aqhome_mqtt.h" + + +void AqHomeMqttLog_HandleSetData(AQHOME_MQTT *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg); + + + +#endif + + + + + diff --git a/apps/aqhome-mqttlog/loop.c b/apps/aqhome-mqttlog/loop.c index ffa0dcc..8cea000 100644 --- a/apps/aqhome-mqttlog/loop.c +++ b/apps/aqhome-mqttlog/loop.c @@ -13,6 +13,7 @@ #include "./loop.h" #include "./loop_ipc.h" #include "./loop_mqtt.h" +#include "./c_setdata.h" #include "./aqhome_mqtt_p.h" #include diff --git a/apps/aqhome-mqttlog/loop_ipc.c b/apps/aqhome-mqttlog/loop_ipc.c index 3f3a9e2..a8fddcb 100644 --- a/apps/aqhome-mqttlog/loop_ipc.c +++ b/apps/aqhome-mqttlog/loop_ipc.c @@ -12,6 +12,7 @@ #include "./loop_ipc.h" #include "./aqhome_mqtt_p.h" +#include "./c_setdata.h" #include "aqhome/ipc/data/ipc_data.h" #include @@ -30,6 +31,8 @@ * ------------------------------------------------------------------------------------------------ */ +static void _handleIpcMsg(AQHOME_MQTT *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg); + /* ------------------------------------------------------------------------------------------------ @@ -45,12 +48,35 @@ void AqHomeMqttLog_ReadAndHandleIpcMessages(AQHOME_MQTT *aqh) epTcp=aqh->brokerEndpoint; while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(epTcp)) ) { + _handleIpcMsg(aqh, epTcp, msg); GWEN_Msg_free(msg); } } +void _handleIpcMsg(AQHOME_MQTT *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg) +{ + uint16_t code; + uint8_t protoId; + + /* exec IPC message */ + code=GWEN_IpcMsg_GetCode(msg); + protoId=GWEN_IpcMsg_GetProtoId(msg); + if (protoId==AQH_IPC_PROTOCOL_DATA_ID) { + DBG_DEBUG(AQH_LOGDOMAIN, "Received IPC packet %d (%x)", (int) code, code); + switch(code) { + case AQH_MSGTYPE_IPC_DATA_SETDATA: AqHomeMqttLog_HandleSetData(aqh, ep, msg); break; + default: break; + } + } + else { + DBG_ERROR(NULL, "Invalid IPC protocol %d (%02x)", protoId, protoId); + } +} + + + diff --git a/apps/aqhome-mqttlog/types/value.t2d b/apps/aqhome-mqttlog/types/value.t2d index 9bb2883..669c145 100644 --- a/apps/aqhome-mqttlog/types/value.t2d +++ b/apps/aqhome-mqttlog/types/value.t2d @@ -48,7 +48,7 @@ 0 0 public - own + own with_getbymember diff --git a/apps/aqhome-tool/data/setdata.c b/apps/aqhome-tool/data/setdata.c index 1b10fbe..2fdbd03 100644 --- a/apps/aqhome-tool/data/setdata.c +++ b/apps/aqhome-tool/data/setdata.c @@ -16,7 +16,7 @@ #include "aqhome/aqhome.h" #include "aqhome/msg/msg_node.h" #include "aqhome/ipc/msg_ipc_result.h" -#include "aqhome/ipc/data/msg_data_multidata.h" +#include "aqhome/ipc/data/msg_data_set.h" #include "aqhome/ipc/data/ipc_data.h" #include @@ -33,7 +33,7 @@ static int _doSetData(GWEN_DB_NODE *dbArgs); -static void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, double dataToSend); +static void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, const char *valueData); @@ -191,9 +191,7 @@ int _doSetData(GWEN_DB_NODE *dbArgs) const char *valueName; const char *valueUnits; const char *valueData; - double dataToSend; GWEN_MSG *msg; - int rv; timeoutInSeconds=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 5); valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL); @@ -209,12 +207,6 @@ int _doSetData(GWEN_DB_NODE *dbArgs) return 1; } - rv=GWEN_Text_StringToDouble(valueData, &dataToSend); - if (rv<0) { - DBG_ERROR(NULL, "ERROR: Invalid data"); - return 1; - } - /*fprintf(stdout, "Sending SetData request\n");*/ @@ -224,7 +216,7 @@ int _doSetData(GWEN_DB_NODE *dbArgs) return 2; } - _sendCommand(epTcp, valueName, valueUnits, dataToSend); + _sendCommand(epTcp, valueName, valueUnits, valueData); for (;;) { uint16_t code; @@ -262,7 +254,7 @@ int _doSetData(GWEN_DB_NODE *dbArgs) -void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, double dataToSend) +void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, const char *valueData) { GWEN_MSG *msgOut; AQH_VALUE *v; @@ -271,7 +263,7 @@ void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *v AQH_Value_SetNameForSystem(v, valueName); AQH_Value_SetValueUnits(v, valueUnits); - msgOut=AQH_MultiDataDataIpcMsg_newForOne(AQH_MSGTYPE_IPC_DATA_SETDATA, v, 0, dataToSend); + msgOut=AQH_SetDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, v, valueData); AQH_Value_free(v); GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut); } diff --git a/devices/tasmota_plug.xml b/devices/tasmota_plug.xml index fe31905..e4d5bab 100644 --- a/devices/tasmota_plug.xml +++ b/devices/tasmota_plug.xml @@ -21,7 +21,7 @@ - cmnd/ + cmnd/tasmota/ /Power