aqhome-mqttlog: Implemented SETDATA.
This commit is contained in:
@@ -55,6 +55,7 @@
|
|||||||
aqhome_mqtt.h
|
aqhome_mqtt.h
|
||||||
aqhome_mqtt_p.h
|
aqhome_mqtt_p.h
|
||||||
xmlread.h
|
xmlread.h
|
||||||
|
c_setdata.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
<sources>
|
<sources>
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
loop_mqtt.c
|
loop_mqtt.c
|
||||||
main.c
|
main.c
|
||||||
xmlread.c
|
xmlread.c
|
||||||
|
c_setdata.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
<useTargets>
|
<useTargets>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
#define AQHOME_MQTT_H
|
#define AQHOME_MQTT_H
|
||||||
|
|
||||||
|
|
||||||
#include "./mqttvalue.h"
|
//#include "./mqttvalue.h"
|
||||||
#include "./mqtttopic.h"
|
//#include "./mqtttopic.h"
|
||||||
#include "aqhome-mqttlog/types/device.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);
|
AQHMQTT_DEVICE_LIST *AqHomeMqtt_GetAvailableDeviceList(const AQHOME_MQTT *aqh);
|
||||||
void AqHomeMqtt_SetAvailableDeviceList(AQHOME_MQTT *aqh, AQHMQTT_DEVICE_LIST *dl);
|
void AqHomeMqtt_SetAvailableDeviceList(AQHOME_MQTT *aqh, AQHMQTT_DEVICE_LIST *dl);
|
||||||
|
|
||||||
|
AQHMQTT_DEVICE *AqHomeMqtt_FindRegisteredDevice(AQHOME_MQTT *aqh, const char *wantedDeviceId);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,8 @@ struct AQHOME_MQTT {
|
|||||||
char *pidFile;
|
char *pidFile;
|
||||||
int timeout; /* timeout for run e.g. inside valgrind */
|
int timeout; /* timeout for run e.g. inside valgrind */
|
||||||
|
|
||||||
AQH_MQTT_VALUE *mqttValueList;
|
|
||||||
AQH_MQTT_TOPIC *mqttTopicList;
|
|
||||||
|
|
||||||
AQHMQTT_DEVICE_LIST *availableDeviceList;
|
AQHMQTT_DEVICE_LIST *availableDeviceList;
|
||||||
AQHMQTT_DEVICE_LIST *registeredDeviceList;
|
AQHMQTT_DEVICE_LIST *registeredDeviceList;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
160
apps/aqhome-mqttlog/c_setdata.c
Normal file
160
apps/aqhome-mqttlog/c_setdata.c
Normal file
@@ -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 <config.h>
|
||||||
|
#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 <gwenhywfar/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* 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:"<empty>");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
25
apps/aqhome-mqttlog/c_setdata.h
Normal file
25
apps/aqhome-mqttlog/c_setdata.h
Normal file
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "./loop.h"
|
#include "./loop.h"
|
||||||
#include "./loop_ipc.h"
|
#include "./loop_ipc.h"
|
||||||
#include "./loop_mqtt.h"
|
#include "./loop_mqtt.h"
|
||||||
|
#include "./c_setdata.h"
|
||||||
#include "./aqhome_mqtt_p.h"
|
#include "./aqhome_mqtt_p.h"
|
||||||
|
|
||||||
#include <gwenhywfar/gwenhywfar.h>
|
#include <gwenhywfar/gwenhywfar.h>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "./loop_ipc.h"
|
#include "./loop_ipc.h"
|
||||||
#include "./aqhome_mqtt_p.h"
|
#include "./aqhome_mqtt_p.h"
|
||||||
|
#include "./c_setdata.h"
|
||||||
#include "aqhome/ipc/data/ipc_data.h"
|
#include "aqhome/ipc/data/ipc_data.h"
|
||||||
|
|
||||||
#include <gwenhywfar/gwenhywfar.h>
|
#include <gwenhywfar/gwenhywfar.h>
|
||||||
@@ -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;
|
epTcp=aqh->brokerEndpoint;
|
||||||
while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(epTcp)) ) {
|
while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(epTcp)) ) {
|
||||||
|
_handleIpcMsg(aqh, epTcp, msg);
|
||||||
GWEN_Msg_free(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<default>0</default>
|
<default>0</default>
|
||||||
<preset>0</preset>
|
<preset>0</preset>
|
||||||
<access>public</access>
|
<access>public</access>
|
||||||
<flags>own</flags>
|
<flags>own with_getbymember</flags>
|
||||||
</member>
|
</member>
|
||||||
|
|
||||||
<member name="valueType" type="int" maxlen="8">
|
<member name="valueType" type="int" maxlen="8">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "aqhome/aqhome.h"
|
#include "aqhome/aqhome.h"
|
||||||
#include "aqhome/msg/msg_node.h"
|
#include "aqhome/msg/msg_node.h"
|
||||||
#include "aqhome/ipc/msg_ipc_result.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 "aqhome/ipc/data/ipc_data.h"
|
||||||
|
|
||||||
#include <gwenhywfar/args.h>
|
#include <gwenhywfar/args.h>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static int _doSetData(GWEN_DB_NODE *dbArgs);
|
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 *valueName;
|
||||||
const char *valueUnits;
|
const char *valueUnits;
|
||||||
const char *valueData;
|
const char *valueData;
|
||||||
double dataToSend;
|
|
||||||
GWEN_MSG *msg;
|
GWEN_MSG *msg;
|
||||||
int rv;
|
|
||||||
|
|
||||||
timeoutInSeconds=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 5);
|
timeoutInSeconds=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 5);
|
||||||
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
|
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
|
||||||
@@ -209,12 +207,6 @@ int _doSetData(GWEN_DB_NODE *dbArgs)
|
|||||||
return 1;
|
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");*/
|
/*fprintf(stdout, "Sending SetData request\n");*/
|
||||||
|
|
||||||
|
|
||||||
@@ -224,7 +216,7 @@ int _doSetData(GWEN_DB_NODE *dbArgs)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendCommand(epTcp, valueName, valueUnits, dataToSend);
|
_sendCommand(epTcp, valueName, valueUnits, valueData);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint16_t code;
|
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;
|
GWEN_MSG *msgOut;
|
||||||
AQH_VALUE *v;
|
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_SetNameForSystem(v, valueName);
|
||||||
AQH_Value_SetValueUnits(v, valueUnits);
|
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);
|
AQH_Value_free(v);
|
||||||
GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut);
|
GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</mqtttopic>
|
</mqtttopic>
|
||||||
|
|
||||||
<mqtttopic type="num" direction="out" >
|
<mqtttopic type="num" direction="out" >
|
||||||
<beforeId>cmnd/</beforeId>
|
<beforeId>cmnd/tasmota/</beforeId>
|
||||||
<afterId>/Power</afterId>
|
<afterId>/Power</afterId>
|
||||||
|
|
||||||
<values>
|
<values>
|
||||||
|
|||||||
Reference in New Issue
Block a user